Quel format d'image utilise le moins la mémoire: PNG, JPEG ou GIF?

70

Quel format d'image est le plus efficace pour économiser de la mémoire? PNG, JPEG ou GIF?

Tredecies Nocturne
la source
4
Le format du fichier n'a rien à voir avec les textures ou la disposition d'objets.
Kylotan

Réponses:

153

"Mémoire" et "efficacité" sont des termes couramment mal utilisés. Je vais donc vous donner une réponse pour quatre éléments différents susceptibles d'affecter les performances de votre jeu.

Je vais trop simplifier beaucoup trop de choses pour le rendre bref et concis, mais il y a des tonnes d'inexactitudes dans ce texte ci-dessous, alors prenez-le avec une pincée de sel. Cependant, les principaux concepts doivent être compréhensibles.

Espace de rangement

C'est la taille que vos images consomment sur votre distribution de logiciel. Plus vos ressources consomment d'espace, plus le téléchargement (à partir de votre site Web) sera long . Si vous distribuez sur des supports physiques, tels que des CD ou des DVD, vous devrez probablement procéder à de sérieuses optimisations à cet égard.

En général, JPEG compresse le mieux pour les photographies et les images sans bordures nettes. Toutefois, la qualité de vos images sera dégradée, car JPEG utilise une compression avec perte (vous pouvez ajuster le niveau de compression / dégradation lors de l'exportation d'images au format JPEG. Pour plus d'informations, reportez-vous à la documentation de votre logiciel de traitement d'images).

Cependant, aussi bon que soit le format JPEG, il ne prend pas en charge la transparence . Cela est crucial si vous souhaitez que les images apparaissent à travers d'autres personnes ou si vous souhaitez des images aux formes irrégulières. Le format GIF est un bon choix, mais il a été largement remplacé par le format PNG (il n’ya que peu de choses que le format GIF prend en charge mais pas du tout dans la programmation de jeux).

Le format PNG prend en charge la transparence (et la semi-transparence), compresse les données sans dégradation de la qualité (c’est-à-dire qu’il utilise la compression sans perte) et compresse assez bien, mais pas autant que le format JPG.

Le problème se pose lorsque vous avez besoin d'une bonne compression, ainsi que de la transparence. Si les images légèrement dégradées ne vous dérangent pas, vous pouvez utiliser des programmes de quantification PNG tels que pngquant , que vous pouvez tester en ligne sur TinyPNG . Gardez à l'esprit que la dégradation d'image réalisée par la quantification est différente de celle du JPEG (qui inclut la quantification ainsi que d'autres techniques agressives), assurez-vous donc d'essayer les deux, avec une grande variété de réglages.

Si vous souhaitez minimiser de manière agressive la taille de votre distribution, vous pouvez traiter manuellement chaque image comme suit:

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

Conseil: vous pouvez stocker des images dans un format et d'autres dans un autre format.

Il existe d'autres formats spécialisés tels que DXT, ETC et PVRTC. Ils prennent en charge la compression et peuvent également être chargés compressés en mémoire, mais ils ne sont pris en charge que par des GPU spécifiques. La plupart de ces GPU ne prennent en charge qu’un d’eux. Ainsi, à moins que vous ne connaissiez les spécifications matérielles exactes de votre matériel cible (un cas notable est: iPhone / iPad, qui prend en charge les textures PVRTC), évitez ces formats.

Programme mémoire

Je l'ai inclus ici, car c'est ce que l'on appelle couramment "mémoire". Cependant, si votre jeu utilise l’accélération graphique (et si vous créez un jeu après 1998, c’est le cas), la seule chose qui consomme de la mémoire sont vos descripteurs de texture (quelques octets par image), qui effectué par la quantité d’images, et non par leur taille ou leur format (quelques mises en garde, mais la plupart du temps sans importance).

Si votre plate-forme ne dispose pas de mémoire vidéo dédiée, ne fait pas l'objet d'une accélération matérielle ni d'autres cas inhabituels, la section suivante relative à la mémoire VRAM se déroulera totalement ou partiellement dans la RAM, mais les principes fondamentaux seront les mêmes.

Mémoire vidéo

C’est là que vos images seront stockées une fois votre programme exécuté. En général, le format dans lequel vous les avez stockées ne fera aucune différence, toutes les images étant décompressées avant de les charger dans la mémoire vidéo.

Maintenant, la VRAM consommée par vos images sera approximativement width * height * bitdepth pour chaque image chargée dans la VRAM. Il y a quelques points à noter ici:

  1. La largeur et la hauteur dans lesquelles vos images sont stockées dans la VRAM ne correspondront pas nécessairement à celles de votre image d'origine. Certains GPU ne peuvent gérer que les textures de tailles 2, ce qui permet de stocker votre image 320x240 dans un espace de 512x256 de la mémoire VRAM, avec le gaspillage de la mémoire inutilisée. Parfois, vous n'êtes même pas autorisé à charger des textures avec des tailles qui ne sont pas des puissances de 2 (comme dans GLES 1.1).

    Par conséquent, si vous souhaitez réduire l'utilisation de la mémoire VRAM, vous pouvez envisager de créer un atlas sur vos images et de les dimensionner avec une puissance de 2, ce qui présente également l'avantage de réduire le nombre de changements d'état de rendu lors du rendu. Plus sur cela plus tard.

  2. La profondeur de bit est très importante. Habituellement, les textures sont chargées dans la VRAM au format ARGB 32 bits ou XRGB 32 bits, mais si votre matériel peut prendre en charge des profondeurs 16 bits et que la taille en bits de la mémoire ne vous gêne pas, vous pouvez réduire de moitié la quantité de VRAM consommée par chaque image. , ce qui peut être quelque chose d'intéressant à considérer.

  3. Mais quoi que vous fassiez, le facteur le plus important pour déterminer la quantité de VRAM utilisée par votre jeu est la quantité d’images que vous avez dans la VRAM à un moment donné. C’est le nombre que vous voudrez probablement garder aussi bas que possible si vous voulez un jeu performant. Le chargement et le déchargement de textures dans la VRAM étant coûteux, vous ne pouvez pas charger chaque image à chaque fois que vous l'utilisez. Vous devez trouver un équilibre entre le préchargement des images que vous allez probablement utiliser et les décharger lorsque vous êtes sûr de ne plus les utiliser. Faire ce droit n'est pas trivial, et vous devez penser à votre propre stratégie pour votre jeu particulier.

Vitesse d'exécution

Même s'il ne s'agit pas de "mémoire", il est très lié à la performance dans les jeux. Dessiner des images coûte cher et vous voulez vous assurer que votre rendu s'exécute aussi vite que possible. Bien sûr, ici, le format n'a pas d'importance, mais il y a d'autres choses qui importent:

  1. Taille de l'image (en fait, il s'agirait de "taille d'échantillonnage"): plus la région d'une image que vous allez dessiner est grande, plus le temps nécessaire pour la dessiner est long. Le rendu d’une grande image dans une petite partie de l’écran n’est pas très efficace. Il existe donc une technique appelée mipmapping , qui consiste à échanger de la VRAM pour obtenir une vitesse de rendu rapide, en stockant vos images plusieurs fois à différentes résolutions et en utilisant la plus petite qui puisse donner. vous la qualité requise à tout moment. Le mappage MIP peut être effectué lorsque les images sont chargées, ce qui affectera la vitesse de chargement et l'utilisation de la mémoire VRAM, ou lors du prétraitement (en stockant manuellement différentes versions de la même image, ou en utilisant un format prenant en charge le mipmapping, tel que DDS), ce qui affectera le stockage. l’utilisation de la VRAM, mais aura peu d’impact sur la vitesse de chargement.

  2. Rendre les changements d'état. Vous voudrez probablement dessiner plusieurs images différentes sur l'écran en même temps. Cependant, le GPU ne peut utiliser qu’une seule image source à la fois (ce n’est pas vrai, mais je vous prie de bien vouloir rester ici avec moi). L'image actuellement utilisée pour le rendu est l'un des nombreux états de rendu , et elle est chère. Donc, si vous allez utiliser la même image plusieurs fois (rappelez-vous quand j'ai mentionné les atlas de texture ?), Vous remarquerez un énorme gain de performances si vous réutilisez une image autant que vous le pouvez avant de changer l'état de rendu et de commencer à utiliser une image. image différente (il existe d'autres états de rendu en dehors de cela, et le réglage précis de l'ordre dans lequel vous tracez vos éléments pour minimiser les changements d'état de rendu est une activité très courante lors de l'amélioration des performances d'un jeu)

Cependant , l'optimisation de l'utilisation des images est un sujet très complexe, et ce que j'ai écrit ici est un aperçu très large et simplifié de certains des facteurs à prendre en compte lors de l'écriture d'un jeu. Je pense donc que c'est mieux si vous restez simple. et n'optimisez que lorsque vous en avez vraiment besoin. La plupart du temps, l'optimisation prématurée est inutile (et parfois même préjudiciable), alors prenez-le doucement.

Pyjama panda
la source
25
+1 C'est une réponse extrêmement complète qui couvre énormément de terrain. Je ne suis pas sûr que la taille des descripteurs de texture nécessite autant de place que nécessaire, et la mention DXT / ETC / PVRTC devrait indiquer que chacune de ces fonctions ne fonctionne que sur certaines plates-formes - elles ne sont pas ouvertes multiplate-forme. normes qui sont utilisables partout, comme JPEG, PNG et GIF. Mais dans l'ensemble, très impressionné. C'est beaucoup plus qu'une simple "annotation mineure" en plus de ma réponse! : D
Trevor Powell le
9
@PandaPajama: Peut-être pas, mais c'est une réponse étonnamment meilleure que cette question ne le mérite.
Marcks Thomas
1
+1, et plus si je pouvais. C’est une excellente réponse, qui devrait constituer un point de référence standard pour toute question sur «l’efficacité de la mémoire», car elle élimine si efficacement le mythe selon lequel utiliser moins de mémoire est toujours la meilleure approche, et pas seulement pour les images. Un élément que je suggérerais d'ajouter est que, dans le cas non accéléré, si une décompression à la volée est nécessaire lors de son dessin, cela pourrait représenter un surcoût inacceptable pour la performance.
Maximus Minimus
2
Je voudrais suggérer PNGGauntlet . Il peut faire d’énormes optimisations sans perte pour les tailles de fichiers PNG, ce qui peut s’ajouter, en particulier lorsque vous avez plusieurs sprites. Malheureusement, il s’agit uniquement de Windows, mais des alternatives sont répertoriées sur la page d’accueil des autres systèmes d’exploitation.
Orlp
1
@DavidDimalanta Je n'ai aucune expérience de libgdx, mais comme je peux le voir dans la documentation setEnforcePotImages, cela désactive l'application de la puissance de textures de taille 2 pour OpenGLES 1.0. Ce n'est pas une bonne idée, car tout le matériel ne prend pas en charge les textures non puissantes. OpenGLES 2.0 nécessite la prise en charge des textures non puissantes, de sorte que si vous ciblez 2.0, vous pouvez utiliser des textures de toute taille. Pour plus d'informations, reportez-vous à la documentation de libgdx.
Panda Pyjama
26

Une fois qu'une image est chargée à partir du disque et formatée pour le rendu, elle utilisera la même quantité de mémoire, que cette image ait été enregistrée sur le disque au format PNG, JPEG ou GIF.

Règle générale: JPEG est un format avec perte qui dégradera la qualité de l’image afin de réduire la taille de l’image sur le disque. Le format PNG, en revanche, est un format d’image sans perte, ce qui entraîne généralement une plus grande taille des fichiers sur le disque. Le format GIF est également techniquement un format sans perte, mais il ne prend en charge que 256 couleurs maximum par image. Par conséquent, une image haute couleur entraîne souvent une lourde perte de qualité si elle est enregistrée au format GIF.

Ce n'est que pour leur représentation sur disque, cependant. En mémoire, ils développeront tous les deux le même format de texture, en utilisant la même quantité de mémoire, que vous les ayez enregistrés sur le disque au format PNG, JPEG ou GIF.

Trevor Powell
la source
Donc, ce n'est pas l'extension de fichier qui varie la taille de la mémoire mais la taille du fichier?
Tredecies Nocturne
Ni. La taille en mémoire est basée sur les dimensions et la profondeur de l'image. Toute compression sur le fichier image est supprimée lorsque l'image est chargée en mémoire pour être dessinée à l'écran. (Parce que les GPU ne peuvent pas restituer les PNG, les JPEG ou les autres. Les images sont développées en pixmaps génériques afin que les GPU puissent les gérer.)
Trevor Powell
2
Ce n'est pas vrai à 100%. La plupart des GPU modernes (y compris ceux intégrés) prennent en charge le chargement et le stockage des textures compressées dans la mémoire graphique, les formats tels que DXT, ETC et PVRTC étant les plus répandus dans le monde intégré. Bien sûr, vous devriez commencer par stocker vos textures dans ces formats au lieu de PNG / JPG / GIF.
Panda Pyjama
6
La question portait sur un choix explicite entre PNG / JPG / GIF, aucun d’entre eux n’étant pris en charge de manière native sur un GPU à ma connaissance. Le demandeur initial avait assez de problèmes avec la distinction entre la taille du fichier sur le disque et l’espace occupé en RAM, mais j’ai estimé que l’ajout de plusieurs formats de fichier ne ferait que confondre le problème fondamental. N'hésitez pas à donner votre propre réponse, cependant.
Trevor Powell
2
Mon commentaire est juste une annotation. Si je devais donner une réponse, j'aurais très probablement écrit la même chose que vous, plus mon commentaire en guise de déclaration finale. Je n'ai rien d'autre à ajouter, je vais donc éviter les répétitions en fournissant ma propre réponse.
Panda Pyjama
3

Ça dépend.

Jpeg est le plus efficace pour les photographies. Ce n'est pas sans perte, mais les artefacts introduits par la compression sont moins visibles dans ce cas d'utilisation.

Le format PNG est sans perte et plus efficace pour les pixel-art avec des lignes nettes et peu de couleurs. Il prend également en charge la transparence alpha.

Le format GIF ne peut rien faire Le PNG ne peut pas faire mieux, à l'exception de sa capacité à stocker des animations. Mais cela n’est pertinent que dans le contexte des applications Web. En développement de jeu, vous créez généralement des animations à l'aide d'un tableur.

Notez que lorsque vous utilisez un moteur graphique tel que Libgdx, il sera probablement décompressé les images juste après leur chargement, puis conservé en mémoire sous forme de valeurs RGBA non compressées. Ainsi, le format de l'image n'a d'importance que pour la vitesse de chargement et dispose d'un espace disque (ou d'une utilisation de la bande passante lorsque vous les envoyez sur le net).

Philipp
la source
2

Je ne connais pas grand chose de libgdx, mais des formats d’image et des graphiques:

JPEG est très bon dans les cas de photos du monde réel. Elles entraînent des pertes, mais vous ne verrez pas d'artefacts sur les photos, sauf si vous prenez des photos avec des bords nets avec des espaces colorés, tels que du texte écrit ou des bandes dessinées. Utilisez-les pour les grands graphiques d'arrière-plan.

GIF est obsolète, il ne peut stocker que des couleurs palettisées (jusqu'à 8 bits par pixel) avec une couleur dédiée pour une transparence complète. Il permet de petites animations basées sur des cadres. Il était une fois un brevet sur son algorithme d'empaquetage afin qu'il ne puisse pas être utilisé partout légalement. À cause de ce brevet, PNG a été développé.

Le format PNG est plus ou moins un bitmap compressé pouvant stocker des formats de pixels RVB + alpha (jusqu’à 32 bits) et autres. Il est spécialisé dans la décompression rapide de petites parties de cette image, ce qui est pratique pour les appareils très petits et lents (comme un téléphone portable de 10 ans), mais les bibliothèques actuelles ne font que les décompresser en bitmaps lors du chargement.

Le format PNG est meilleur que le format GIF en termes de taille, de rapidité et de fonctionnalités, mais si vous souhaitez stocker efficacement les bitmaps, je vous conseillerais: que .PNG. [/ edit])

PNM / PBM / PGM / PAM sont des formats bitmap simples avec des en-têtes KISS en texte brut. L'utilisation de gzip sur ceux-ci donnera une taille de fichier similaire à celle du fichier PNG. Bzip2 est donc la meilleure solution pour cela. Si vous souhaitez utiliser des bitmaps en interne dans votre programme, vous pouvez utiliser des bitmaps compressés bzip2 dans un conteneur .tar ou .zip. Si vous n'avez pas bzip2, utiliser des fichiers PNM dans un conteneur zip (zip avec compression maximale) peut être similaire à utiliser des fichiers PNG. - Ainsi, le stockage des fichiers PNG dans un fichier ZIP n’a que peu d’avantages, voire aucun avantage - cela augmenterait probablement le temps nécessaire au chargement de l’image.

En outre, il est judicieux de stocker plusieurs images-objets / images-sprites dans une même image, en particulier si vous en avez besoin dans la même situation.

comonad
la source
Le fichier PNM est-il disponible et lisible par tous les systèmes d'exploitation de smartphone et d'ordinateur de bureau?
David Dimalanta
1
@ David Dimalanta: Je ne sais pas où il est pris en charge et où il ne l'est pas. Si vous souhaitez programmer avec des PNM, vous ne voudrez probablement jamais utiliser aucune bibliothèque, car ce format est trop simple pour choisir une API. De ce fait, il est lisible et inscriptible avec tous les langages de programmation existants prenant en charge la lecture / écriture de fichiers binaires. Bien sûr, vous pouvez utiliser Netpbm sur n’importe quel système d’exploitation, pas seulement sous Unix. D'autre part, je ne sais pas quelles bibliothèques d'images générales ne supportent pas cela. Ce n'est pas un format compressé, il est donc rarement utilisé pour stocker des images sur disque. voir en.wikipedia.org/wiki/Netpbm_format
comonad
1

En tant que format de stockage, JPEG est probablement le meilleur choix pour certaines textures telles que l'herbe ou les murs, où la perte d'informations est probablement indétectable. Suivi par PNG lorsque vous avez besoin de transparence ou lorsque vous ne pouvez pas payer avec perte d’informations, par exemple des sprites dans un jeu en 2D (le joueur, des ennemis, un coffre au trésor), vous voudrez probablement utiliser PNG pour ces images.

En ce qui concerne les coûts de mémoire, le format utilisé pour stocker les graphiques de jeu dans le système de fichiers n’a aucune pertinence. Que vous stockiez des tampons de pixels dans la mémoire VRAM ou RAM (logiciel de rendu logiciel), vous les avez probablement stockés non compressés, car les jeux favorisent la lecture rapide des pixels par rapport à la mémoire utilisée par chaque tampon de pixels.

Les données compressées stockées en mémoire n'ont aucun sens si ce n'est que vous conservez une sorte de cache pour enregistrer les lectures sur disque, mais vous devez probablement lire à partir de ce cache dans un état non compressé pour les images utilisées à un moment donné de votre jeu.

Les données d'image comprimées ont un peu plus de sens si un décodage matériel rapide était possible. Pour le mappage normal au moins, je me souviens de ce http://en.wikipedia.org/wiki/3Dc . Avec cela, vous pouvez économiser de la VRAM. Je ne connais pas encore d'autres exemples de décodage matériel.

En résumé: quels que soient les formats utilisés par votre jeu pour stocker les graphiques dans un stockage persistant, vous devrez le décoder et conserver une version non compressée en mémoire dynamique, en mémoire vidéo ou les deux, afin de pouvoir les restituer rapidement en cas de besoin.

Enfin: je suis un gars de bureau. Quand je dis "mémoire", je me réfère toujours à la mémoire dynamique. Quand je dis "disque", "système de fichiers" ou "stockage persistant", je me réfère toujours à tout ce que votre périphérique utilise comme stockage persistant, généralement, je pense, sur des disques durs. Lorsque vous avez dit "efficacité de la mémoire", je l'ai pris pour "mémoire dynamique" et non pour "stockage persistant". Dernièrement, je vois beaucoup de gens utiliser le mot "mémoire" pour parler de "stockage persistant" (peut-être que la terminologie des appareils mobiles?).

Hatoru Hansou
la source
Est-il possible également que ce ne soit pas le JPEG ni le PNG qui affecte la mémoire mais la taille du fichier?
Tredecies Nocturne le
Oui. Vous choisirez l’un des formats abordés en pensant au gain d’espace disque ou de bande passante. Lors du chargement des images dans le jeu, toutes les bibliothèques / tous les moteurs que je connais les décoderont en tampons de pixels non compressés (pensez aux tampons de pixels sous forme de tableau de valeurs RVB ou RGBA, chaque canal occupant généralement 1 octet en RAM / VRAM si vous utilisez 32 bits par seconde). pixels, c’est probablement ce que tout le monde fait).
Hatoru Hansou