Welches Bildformat ist effizienter, um Speicherplatz zu sparen? PNG, JPEG oder GIF?
Welches Bildformat ist effizienter, um Speicherplatz zu sparen? PNG, JPEG oder GIF?
Antworten:
"Gedächtnis" und "Effizienz" sind häufig missbrauchte Begriffe, daher werde ich Ihnen eine Antwort auf vier verschiedene Elemente geben, die sich auf die Leistung Ihres Spiels auswirken können.
Ich werde viel zu viele Dinge zu stark vereinfachen, um sie kurz und prägnant zu halten, aber es gibt Unmengen von Ungenauigkeiten in diesem Text unten, also nimm es mit einer Prise Salz. Die wichtigsten Konzepte sollten jedoch verständlich sein.
Lager
Dies ist die Größe, die Ihre Bilder für Ihre Softwareverteilung benötigen. Je mehr Speicherplatz Ihre Ressourcen belegen, desto länger dauert der Download (wie von Ihrer Website). Wenn Sie auf physischen Medien wie CDs oder DVDs verteilen, müssen Sie an dieser Stelle wahrscheinlich einige gravierende Optimierungen vornehmen.
Im Allgemeinen komprimiert JPEG am besten Fotos und Bilder ohne scharfe Ränder. Ihre Bilder haben jedoch eine schlechtere Qualität, da JPEG verlustbehaftete Komprimierung verwendet (Sie können die Komprimierungsstufe / -verschlechterung beim Exportieren von Bildern als JPEG fein einstellen . Weitere Informationen hierzu finden Sie in der Dokumentation Ihrer Bildbearbeitungssoftware.)
So gut JPEG auch sein mag, es unterstützt keine Transparenz . Dies ist von entscheidender Bedeutung, wenn Sie Bilder haben möchten, die durch andere angezeigt werden, oder wenn Sie Bilder mit unregelmäßigen Formen möchten. GIF ist eine gute Wahl, wurde jedoch von PNG weitgehend abgelöst (es gibt nur wenige Dinge, die von GIF unterstützt werden, die von PNG nicht unterstützt werden, für die Spielprogrammierung sind sie jedoch weitgehend irrelevant).
PNG unterstützt Transparenz (und Semitransparenz), komprimiert Daten ohne Qualitätsverlust (dh es verwendet verlustfreie Komprimierung) und komprimiert ziemlich gut, jedoch nicht so viel wie JPG.
Das Problem tritt auf, wenn Sie eine gute Komprimierung sowie Transparenz benötigen. Wenn Sie nichts gegen leicht verschlechterte Bilder haben, können Sie PNG-Quantisierungsprogramme wie pngquant verwenden , die Sie online bei TinyPNG testen können . Denken Sie daran, dass die Bildverschlechterung, die durch die Quantisierung von selbst durchgeführt wird, sich von der von JPEG unterscheidet (einschließlich Quantisierung und anderer aggressiver Techniken). Versuchen Sie also unbedingt beides mit einer Vielzahl von Einstellungen.
Wenn Sie Ihre Verteilungsgröße aggressiv minimieren möchten, können Sie jedes Bild wie folgt manuell verarbeiten:
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
Tipp: Es ist in Ordnung, einige Bilder in einem Format und andere in einem anderen Format zu speichern.
Es gibt andere spezialisierte Formate wie DXT, ETC und PVRTC. Sie unterstützen die Komprimierung und können auch komprimiert in den Speicher geladen werden. Sie werden jedoch nur von bestimmten GPUs unterstützt, und die meisten dieser GPUs unterstützen nur eine von ihnen. Wenn Sie also nicht die genauen Hardwarespezifikationen Ihrer Zielhardware kennen (dies ist ein bemerkenswerter Fall) Auf dem iPhone / iPad, das PVRTC-Texturen unterstützt, sollten Sie diese Formate meiden.
Programmspeicher
Ich habe es hier aufgenommen, weil dies allgemein als "Erinnerung" bekannt ist. Wenn Ihr Spiel jedoch Grafikbeschleunigung verwendet (und wenn Sie ein Spiel nach 1998 erstellen, ist dies höchstwahrscheinlich der Fall), werden nur Ihre Texturdeskriptoren (nur ein paar Bytes pro Bild) Speicher belegen Dies hängt von der Anzahl der Bilder und nicht von deren Größe oder Format ab (dies weist einige Einschränkungen auf, ist jedoch meistens irrelevant).
Wenn Ihre Plattform keinen dedizierten Videospeicher hat, nicht hardwarebeschleunigt ist oder in anderen seltenen Fällen, wird der nächste Abschnitt in Bezug auf VRAM ganz oder teilweise im RAM ausgeführt, die Hauptprinzipien sind jedoch dieselben.
Videospeicher
Hier werden Ihre Bilder gespeichert, sobald Ihr Programm ausgeführt wird. Im Allgemeinen spielt das Format, in dem Sie sie gespeichert haben, keine Rolle, da alle Bilder vor dem Laden in den Videospeicher dekomprimiert werden.
Der von Ihren Bildern aufgenommene VRAM wird nun ungefähr width * height * bitdepth
für jedes in den VRAM geladene Bild verwendet. Hier sind einige Dinge zu beachten:
Die Breite und Höhe, in der Ihre Bilder im VRAM gespeichert werden, müssen nicht mit denen Ihres Originalbilds übereinstimmen. Einige GPUs können nur Texturen mit einer Größe in Zweierpotenzen verarbeiten, sodass Ihr 320x240-Bild möglicherweise tatsächlich in einem 512x256-Bereich im VRAM gespeichert wird und der nicht verwendete Speicher effektiv verschwendet wird. Manchmal dürfen Sie nicht einmal Texturen mit Größen laden, die nicht Potenzen von 2 haben (wie in GLES 1.1).
Wenn Sie also die VRAM-Nutzung minimieren möchten, sollten Sie erwägen, Ihre Bilder zu atlasieren und mit Zweierpotenzen zu skalieren. Dies hat auch den Vorteil, dass sich beim Rendern weniger Änderungen am Renderstatus ergeben. Dazu später mehr.
Die Bittiefe ist sehr wichtig. Normalerweise werden Texturen in 32-Bit-ARGB oder 32-Bit-XRGB in den VRAM geladen. Wenn Ihre Hardware jedoch 16-Bit-Tiefen unterstützt und es Ihnen nichts ausmacht, eine niedrigere Bit-Tiefe zu haben, können Sie die Hälfte des von jedem Bild verbrauchten VRAMs verwenden , was interessant sein könnte.
Unabhängig davon, was Sie tun, ist die Anzahl der Bilder, die Sie zu einem bestimmten Zeitpunkt im VRAM haben, der wichtigste Faktor, wenn Sie die Menge an VRAM in Ihrem Spiel berücksichtigen . Dies ist die Zahl, die Sie höchstwahrscheinlich so niedrig wie möglich halten möchten, wenn Sie ein Spiel mit guter Leistung wünschen. Das Laden und Entladen von Texturen in VRAM ist teuer, sodass Sie nicht jedes Bild einfach laden können, wenn Sie es verwenden möchten. Sie müssen ein Gleichgewicht zwischen dem Vorabladen der Bilder finden, die Sie höchstwahrscheinlich verwenden werden, und dem Entladen, wenn Sie sicher sind, dass Sie sie nicht mehr verwenden werden. Es ist nicht trivial, dies richtig zu machen, und Sie müssen sich Ihre eigene Strategie für Ihr bestimmtes Spiel überlegen.
Ausführungsgeschwindigkeit
Auch wenn es kein "Gedächtnis" ist, hängt es sehr mit der Leistung in Spielen zusammen. Das Zeichnen von Bildern ist teuer und Sie möchten sicherstellen, dass das Rendern so schnell wie möglich ausgeführt wird. Natürlich spielt hier das Format keine Rolle, aber andere Dinge tun es:
Bildgröße (eigentlich "Abtastgröße"): Je größer der Bereich eines Bildes ist, den Sie zeichnen möchten, desto länger dauert das Zeichnen. Das Rendern eines großen Bilds in einem kleinen Bereich des Bildschirms ist nicht sehr effektiv. Daher gibt es eine Technik namens Mipmapping , bei der VRAM für die Rendergeschwindigkeit ausgetauscht wird , indem Ihre Bilder mehrmals mit verschiedenen Auflösungen gespeichert werden und die kleinste verwendet wird, die es gibt Sie die gewünschte Qualität zu einem bestimmten Zeitpunkt. Mipmapping kann ausgeführt werden, wenn die Bilder geladen werden, was sich auf die Ladegeschwindigkeit und die VRAM-Nutzung auswirkt, oder bei der Vorverarbeitung (indem verschiedene Versionen desselben Bildes manuell gespeichert werden oder ein Format verwendet wird, das Mipmapping von Haus aus unterstützt, z. B. DDS), was sich auf die Speicherung auswirkt und VRAM-Nutzung, hat aber nur geringen Einfluss auf die Ladegeschwindigkeit.
Statusänderungen rendern. Sie möchten höchstwahrscheinlich mehrere verschiedene Bilder gleichzeitig auf dem Bildschirm zeichnen. Die GPU kann jedoch jeweils nur ein einziges Quellbild verwenden (dies ist nicht der Fall, bitte nehmen Sie dies hier mit). Das derzeit zum Rendern verwendete Bild ist einer von vielen Renderzuständen und teuer. Wenn Sie also dasselbe Bild mehrmals verwenden (erinnern Sie sich, als ich Texturatlanten erwähnte ?), Werden Sie einen enormen Leistungsgewinn bemerken, wenn Sie ein Bild so oft wie möglich wiederverwenden, bevor Sie den Render-Status ändern und a verwenden anderes Bild (abgesehen davon gibt es noch andere Render-Zustände, und die Feinabstimmung der Reihenfolge, in der Sie Ihre Inhalte zeichnen, um Änderungen des Render-Zustands zu minimieren, ist eine sehr häufige Aktivität bei der Verbesserung der Leistung eines Spiels.)
Die Optimierung der Bildnutzung ist jedoch ein sehr komplexes Thema, und was ich hier geschrieben habe, ist ein sehr umfassender und vereinfachter Überblick über einige der Faktoren, die Sie beim Schreiben eines Spiels berücksichtigen müssen. Ich denke, es ist auf jeden Fall am besten, wenn Sie es einfach halten. und optimieren Sie nur, wenn Sie es wirklich brauchen. In den meisten Fällen ist eine vorzeitige Optimierung nicht erforderlich (und manchmal sogar nachteilig).
setEnforcePotImages
, deaktiviert es die Durchsetzung von Power von Texturen mit 2 Größen für OpenGLES 1.0. Dies ist keine gute Idee, da nicht jede Hardware Nicht-Power-of-2-Texturen unterstützt. OpenGLES 2.0 erfordert die Unterstützung von Nicht-Power-of-2-Texturen. Wenn Sie also auf 2.0 abzielen, können Sie Texturen beliebiger Größe verwenden. Weitere Informationen finden Sie in der libgdx-Dokumentation.
Sobald ein Bild von der Festplatte geladen und zum Rendern formatiert wurde, wird dieselbe Speichermenge verwendet, unabhängig davon, ob das Bild mit PNG, JPEG oder GIF auf der Festplatte gespeichert wurde.
Allgemeine Faustregel: JPEG ist ein verlustbehaftetes Format und beeinträchtigt die Bildqualität, um das Bild auf der Festplatte zu verkleinern. PNG hingegen ist ein verlustfreies Bildformat und führt normalerweise zu größeren Dateien auf der Festplatte. GIF ist auch technisch gesehen ein verlustfreies Format, unterstützt jedoch nur maximal 256 Farben pro Bild, sodass ein Bild mit hohen Farben beim Speichern als GIF häufig einen erheblichen Qualitätsverlust erleidet.
Das ist jedoch nur für die Darstellung auf der Festplatte. Im Arbeitsspeicher werden beide in dasselbe Texturformat expandiert, wobei dieselbe Speichermenge verwendet wird, unabhängig davon, ob Sie sie als PNG, als JPEG oder als GIF auf der Festplatte gespeichert haben.
Es hängt davon ab, ob.
JPEG ist für Fotographien am leistungsfähigsten. Es ist nicht verlustfrei, aber die durch die Komprimierung eingebrachten Artefakte sind in diesem Anwendungsfall am wenigsten sichtbar.
PNG ist verlustfrei und für Pixelkunst mit scharfen Linien und wenigen Farben am effizientesten. Es unterstützt auch Alpha-Transparenz.
GIF kann nichts, was PNG nicht besser kann, außer die Möglichkeit, Animationen zu speichern. Dies ist jedoch nur im Zusammenhang mit Webanwendungen relevant. In der Spieleentwicklung erstellen Sie Animationen normalerweise mithilfe eines Spritesheets.
Wenn Sie eine Grafik-Engine wie Libgdx verwenden, werden die Bilder höchstwahrscheinlich direkt nach dem Laden dekomprimiert und als unkomprimierte RGBA-Werte gespeichert. Das Bildformat ist also nur für die Ladegeschwindigkeit von Bedeutung und hat Speicherplatz (oder Bandbreitennutzung, wenn Sie sie über das Netz senden).
Ich weiß nicht viel über libgdx, aber über Bildformate und Grafiken:
JPEG ist sehr gut für Fotos aus der realen Welt. Sie sind verlustbehaftet, aber Sie werden keine Artefakte auf Fotos sehen, es sei denn, Sie machen Bilder mit scharfen Kanten und einfarbigen Zwischenräumen, wie zum Beispiel geschriebenen Text oder Comics. Verwenden Sie sie für große Hintergrundgrafiken.
GIF ist veraltet, es können nur Farben mit Paletten (bis zu 8 Bit pro Pixel) mit einer bestimmten Farbe gespeichert werden, um vollständige Transparenz zu gewährleisten. Es erlaubt kleine Animationen basierend auf Frames. Es gab einmal ein Patent für seinen Verpackungsalgorithmus, so dass er nicht überall legal verwendet werden konnte. Aufgrund dieses Patents wurde PNG entwickelt.
PNG ist mehr oder weniger eine gezippte Bitmap, die RGB + Alpha (bis zu 32 Bit) und andere Pixelformate speichern kann. Es ist auf das schnelle Entpacken kleiner Teile dieses Bildes spezialisiert, was für sehr kleine und langsame Geräte (wie ein 10 Jahre altes Mobiltelefon) praktisch ist, aber die heutigen Bibliotheken entpacken sie beim Laden einfach in Bitmaps.
PNG ist in Größe, Geschwindigkeit und Funktionen besser als GIF, aber wenn Sie Bitmaps effizient speichern möchten, würde ich Folgendes vorschlagen: .PNM.BZ2 ([Bearbeiten] Aufgrund der unterschiedlichen Packmethoden ist .PNM.BZ2 nicht immer effizienter als .PNG. [/ edit])
PNM / PBM / PGM / PAM sind einfache Bitmap-Formate mit KISS-Headern im Klartext. Die Verwendung von gzip führt zu einer Dateigröße, die der von PNG ähnelt. Daher ist bzip2 die bessere Lösung. Wenn Sie Bitmaps programmintern verwenden möchten, können Sie bzip2-komprimierte Bitmaps in einem .tar- oder .zip-Container verwenden. Wenn Sie nicht über bzip2 verfügen, ähnelt die Verwendung von PNMs in einem Zip-Container (Zip mit maximaler Komprimierung) möglicherweise der Verwendung von PNGs. - Das Speichern von PNGs in einer ZIP-Datei hat daher möglicherweise nur geringe oder gar keine Vorteile - es würde wahrscheinlich nur die Zeit zum Laden des Bildes verlängern.
Außerdem ist es eine gute Wahl, mehrere kleine Sprites / Bilder in einer Bitmap zu speichern, insbesondere wenn Sie alle in derselben Situation zusammen benötigen.
Als Speicherformat ist JPEG wahrscheinlich die beste Wahl für einige Texturen wie Gras oder Wände, bei denen der Informationsverlust wahrscheinlich nicht nachweisbar ist. Gefolgt von PNG, wenn Sie Transparenz benötigen oder wenn Sie nicht mit Informationsverlust bezahlen können, z. B. Sprites in einem 2D-Spiel (der Spieler, Feinde, eine Schatzkiste), möchten Sie wahrscheinlich PNG für diese Bilder verwenden.
Wenn es um die Speicherkosten geht, ist das Format, in dem die Spielgrafiken im Dateisystem gespeichert werden, überhaupt nicht relevant. Wenn Sie Pixelpuffer im VRAM oder im RAM (Software-Renderer) speichern, werden sie wahrscheinlich unkomprimiert gespeichert, da Spiele das schnelle Lesen von Pixeln im Vergleich zum von jedem Pixelpuffer verwendeten Speicher bevorzugen.
Komprimierte Daten im Speicher zu haben, hat keinen Sinn, es sei denn, Sie verwalten eine Art Cache, um Lesezugriffe auf die Festplatte zu speichern. Wahrscheinlich müssen Sie jedoch für die Bilder, die zu einem bestimmten Zeitpunkt in Ihrem Spiel verwendet werden, aus diesem Cache in einen nicht komprimierten Zustand lesen.
Komprimierte Bilddaten sind etwas sinnvoller, wenn eine schnelle Hardware-Dekodierung möglich wäre. Zumindest für die normale Zuordnung erinnere ich mich an diese http://en.wikipedia.org/wiki/3Dc . Damit können Sie ein wenig VRAM sparen. Andere Beispiele für die Hardware-Dekodierung sind mir noch nicht bekannt.
Fazit: Unabhängig von den Formaten, die in Ihrem Spiel zum Speichern von Grafiken in einem dauerhaften Speicher verwendet werden, müssen Sie diese dekodieren und eine unkomprimierte Version im dynamischen Speicher, im Videospeicher oder in beiden speichern, um sie bei Bedarf schnell rendern zu können.
Endlich: Ich bin ein Desktop-Typ. Wenn ich "Gedächtnis" sage, beziehe ich mich immer auf dynamisches Gedächtnis. Wenn ich "Festplatte", "Dateisystem" oder "persistenter Speicher" sage, beziehe ich mich immer auf das, was Ihr Gerät als persistenten Speicher verwendet, normalerweise denke ich an Festplatten. Wenn Sie "Speichereffizienz" sagten, habe ich es als "dynamischen Speicher" und nicht als "dauerhaften Speicher" bezeichnet. In letzter Zeit verwenden viele Leute das Wort "Speicher", um sich auf "dauerhaften Speicher" zu beziehen (vielleicht die Terminologie von Mobilgeräten?).