Który format obrazu jest bardziej wydajny w celu oszczędzania pamięci? PNG, JPEG lub GIF?
graphics
graphics-programming
image
memory-efficiency
Tredecies Nocturne
źródło
źródło
Odpowiedzi:
„Pamięć” i „wydajność” są często niewłaściwie używanymi terminami, więc dam ci odpowiedź na cztery różne elementy, które mogą wpłynąć na wydajność twojej gry.
Będę nadmiernie upraszczał zbyt wiele rzeczy, aby było krótkie i zwięzłe, ale w tekście poniżej jest mnóstwo niedokładności, więc weź to ze szczyptą soli. Jednak główne pojęcia powinny być zrozumiałe.
Przechowywanie
Jest to rozmiar, jaki zużywają Twoje obrazy w dystrybucji oprogramowania. Im więcej miejsca zajmują zasoby, tym dłużej trwa pobieranie (tak jak w witrynie). Jeśli dystrybuujesz na nośnikach fizycznych, takich jak dyski CD lub DVD, prawdopodobnie będziesz musiał dokonać poważnych optymalizacji w tym zakresie.
Ogólnie JPEG kompresuje najlepiej dla zdjęć i obrazów bez ostrych ramek. Jednak zdjęcia będą miały obniżoną jakość, ponieważ JPEG stosuje kompresję stratną (można wyregulować poziom kompresji / degradację podczas eksportowania obrazów jako JPEG. Więcej informacji na ten temat można znaleźć w dokumentacji oprogramowania do przetwarzania obrazu).
Jednak tak dobry, jak JPEG, nie obsługuje przezroczystości . Jest to bardzo ważne, jeśli chcesz mieć obrazy, które pokazują inne lub jeśli chcesz obrazy o nieregularnych kształtach. GIF to dobry wybór, ale został w dużej mierze zastąpiony przez PNG (istnieje tylko kilka rzeczy, które GIF obsługuje, ale PNG nie są one w dużej mierze nieistotne w programowaniu gier).
PNG obsługuje przezroczystość (i półprzezroczystość), kompresuje dane bez pogorszenia jakości (tj. Używa kompresji bezstratnej) i kompresuje dość dobrze, ale nie tak bardzo jak JPG.
Problem pojawia się, gdy potrzebujesz dobrej kompresji, a także przejrzystości. Jeśli nie masz nic przeciwko nieznacznie zdegradowanym obrazom, możesz użyć programów do kwantyzacji PNG, takich jak pngquant , które możesz przetestować online w TinyPNG . Należy pamiętać, że degradacja obrazu przeprowadzana przez samą kwantyzację jest inna niż w przypadku formatu JPEG (który obejmuje kwantyzację, a także inne agresywne techniki), więc wypróbuj oba sposoby, korzystając z szerokiej gamy ustawień.
Jeśli chcesz agresywnie zminimalizować rozmiar swojej dystrybucji, możesz ręcznie przetworzyć każdy obraz w ten sposób:
Wskazówka: można przechowywać niektóre obrazy w jednym formacie, a inne w innym formacie.
Istnieją inne specjalistyczne formaty, takie jak DXT, ETC i PVRTC. Obsługują kompresję, a także mogą być ładowane skompresowane do pamięci, ale są obsługiwane tylko przez określone procesory graficzne, a większość z tych GPU obsługuje tylko jeden z nich, więc jeśli nie znasz dokładnej specyfikacji sprzętu docelowego (godnym uwagi przypadkiem jest iPhone / iPad, który obsługuje tekstury PVRTC), należy unikać tych formatów.
Pamięć programu
Włączyłem go tutaj, ponieważ to jest to, co powszechnie znane jest pod nazwą „pamięć”. Jeśli jednak gra korzysta z akceleracji grafiki (a jeśli tworzysz ją po 1998 r., Najprawdopodobniej tak jest), jedyną rzeczą, która zużyje pamięć, są deskryptory tekstur (zaledwie kilka bajtów na obraz), które są tylko zależy od ilości zdjęć, a nie od ich wielkości lub formatu (ma to kilka zastrzeżeń, ale w większości są nieistotne).
Jeśli Twoja platforma nie ma dedykowanej pamięci wideo, nie jest przyspieszana sprzętowo lub w innych nietypowych przypadkach, następna sekcja dotycząca pamięci VRAM wydarzy się całkowicie lub częściowo w pamięci RAM, ale główne zasady będą takie same.
Pamięć wideo
Tutaj będą przechowywane twoje obrazy po uruchomieniu programu. Ogólnie rzecz biorąc, format, w którym je zapisałeś, nie ma znaczenia, ponieważ wszystkie obrazy są dekompresowane przed załadowaniem ich do pamięci wideo.
Teraz pamięć VRAM zużywana przez obrazy będzie w przybliżeniu odpowiadać
width * height * bitdepth
każdemu obrazowi załadowanemu do pamięci VRAM. Można tutaj zauważyć kilka rzeczy:Szerokość i wysokość, w której obrazy są przechowywane w pamięci VRAM, niekoniecznie muszą odpowiadać oryginalnym obrazom. Niektóre procesory graficzne obsługują tylko tekstury o rozmiarach o sile 2, więc obraz 320 x 240 może faktycznie być przechowywany w przestrzeni 512 x 256 w pamięci VRAM, a niewykorzystana pamięć zostanie skutecznie zmarnowana. Czasami nawet nie możesz ładować tekstur o rozmiarach, które nie są potęgami 2 (jak w GLES 1.1).
Więc jeśli chcesz, aby zminimalizować zużycie VRAM, może chcesz rozważa atlasing swoje obrazy, a ich rozmiary uprawnień 2, które będą miały również tę zaletę, że mniej czynią zmian stanu podczas renderowania. Więcej na ten temat później.
Bitdepth jest bardzo ważny. Zwykle tekstury są ładowane do VRAM w 32-bitowym ARGB lub 32-bitowym XRGB, ale jeśli twój sprzęt może obsługiwać 16-bitowe głębokości i nie masz nic przeciwko niższej głębi bitów, możesz zmniejszyć o połowę ilość pamięci VRAM zużywanej przez każdy obraz , co może być interesujące.
Ale bez względu na to, co robisz, najważniejszym czynnikiem przy rozważaniu ilości pamięci VRAM używanej przez grę jest liczba obrazów w pamięci VRAM w danym momencie. Jest to liczba, którą najprawdopodobniej chcesz utrzymać na jak najniższym poziomie, jeśli chcesz mieć dobrą grę. Ładowanie i rozładowywanie tekstur do pamięci VRAM jest drogie, więc nie możesz po prostu załadować każdego obrazu, gdy tylko będziesz go używać. Musisz znaleźć równowagę między wstępnym ładowaniem obrazów, których najprawdopodobniej użyjesz, a rozładowaniem ich, jeśli masz pewność, że nie będziesz ich już używać. Wykonanie tego prawa nie jest trywialne i musisz pomyśleć o własnej strategii dla konkretnej gry.
Szybkość wykonania
Chociaż nie „pamięć”, jest bardzo związana z wydajnością w grach. Rysowanie obrazów jest drogie i chcesz mieć pewność, że renderowanie przebiega tak szybko, jak to możliwe. Oczywiście tutaj format nie ma znaczenia, ale inne rzeczy mają znaczenie:
Rozmiar obrazu (w rzeczywistości byłby to „rozmiar próbki”): im większy region obrazu, który zamierzasz narysować, tym więcej czasu zajmie jego narysowanie. Renderowanie ogromnego obrazu w małej części ekranu nie jest zbyt skuteczne, dlatego istnieje technika zwana mipmapowaniem , która polega na wymianie pamięci VRAM na szybkość renderowania, poprzez przechowywanie obrazów kilka razy w kilku rozdzielczościach i użycie najmniejszej, która może dać wymagana jakość w danym momencie. Mapowanie mipem można wykonać po załadowaniu obrazów, co wpłynie na szybkość ładowania i użycie pamięci VRAM, lub podczas wstępnego przetwarzania (ręcznie przechowując różne wersje tego samego obrazu lub używając formatu, który natywnie obsługuje mapowanie takie jak DDS), co będzie miało wpływ na przechowywanie i użycie pamięci VRAM, ale będzie miało niewielki wpływ na szybkość ładowania.
Zmiany stanu renderowania. Najprawdopodobniej będziesz chciał narysować na ekranie kilka różnych obrazów jednocześnie. Jednak GPU może używać tylko jednego obrazu źródłowego w danym momencie (to nie jest prawda, ale proszę o wyrozumiałość tutaj). Aktualnie używany obraz do renderowania jest jednym z wielu stanów renderowania i jest drogi. Jeśli więc zamierzasz użyć tego samego obrazu kilka razy (pamiętasz, kiedy wspomniałem o atlasach tekstur ?), Zauważysz ogromny wzrost wydajności, jeśli ponownie użyjesz obrazu tak dużo, jak to możliwe, zanim zmienisz stan renderowania i zaczniesz używać inny obraz (oprócz tego istnieją inne stany renderowania, a dostrajanie kolejności rysowania elementów w celu zminimalizowania zmian stanu renderowania jest bardzo częstym działaniem podczas zwiększania wydajności gry)
Jednak optymalizacja wykorzystania obrazu jest bardzo złożonym tematem, a to, co tu napisałem, jest bardzo szerokim i uproszczonym przeglądem niektórych czynników, które należy wziąć pod uwagę przy pisaniu gry, więc myślę, że zdecydowanie najlepiej jest zachować prostotę, i optymalizuj tylko wtedy, gdy naprawdę tego potrzebujesz. W większości przypadków przedwczesna optymalizacja jest niepotrzebna (a czasem nawet szkodliwa), więc spokojnie.
źródło
setEnforcePotImages
, wyłącza to wymuszanie mocy tekstur 2-wymiarowych w OpenGLES 1.0. To nie jest dobry pomysł, ponieważ nie wszystkie urządzenia obsługują tekstury bez zasilania 2. OpenGLES 2.0 wymaga obsługi tekstur innych niż power-of-2, więc jeśli celujesz w 2.0, możesz używać tekstur o dowolnym rozmiarze. Aby uzyskać więcej informacji, zapoznaj się z dokumentacją libgdx.Gdy obraz zostanie załadowany z dysku i sformatowany do renderowania, zużyje tę samą ilość pamięci, niezależnie od tego, czy obraz został zapisany na dysku przy użyciu PNG, JPEG lub GIF.
Ogólna zasada: JPEG jest formatem stratnym i obniża jakość obrazu, aby zmniejszyć obraz na dysku. Z drugiej strony, PNG jest bezstratnym formatem obrazu, dlatego zwykle powoduje zwiększenie rozmiaru pliku na dysku. GIF jest również technicznie formatem bezstratnym, ale obsługuje maksymalnie 256 kolorów na obraz, dlatego obraz w wysokiej rozdzielczości często powoduje znaczną utratę jakości, jeśli jest zapisany jako GIF.
Ale to tylko dla ich reprezentacji na dysku. W pamięci oba rozwiną się do tego samego formatu tekstury, wykorzystując tę samą ilość pamięci, niezależnie od tego, czy zapisałeś je na dysku jako PNG, JPEG czy GIF.
źródło
To zależy.
JPEG jest najbardziej wydajny dla zdjęć. Nie jest bezstratny, ale artefakty wprowadzone przez kompresję są najmniej widoczne w tym przypadku użycia.
PNG jest bezstratny i najbardziej wydajny w przypadku pikseli z ostrymi liniami i kilkoma kolorami. Obsługuje również przezroczystość alfa.
GIF nie może nic zrobić PNG nie może zrobić nic lepszego, oprócz możliwości przechowywania animacji. Jest to jednak istotne tylko w kontekście aplikacji internetowych. Podczas tworzenia gry zazwyczaj tworzysz animacje za pomocą arkusza sprite.
Zauważ, że kiedy używasz silnika graficznego takiego jak Libgdx, najprawdopodobniej rozpakuje on obrazy zaraz po ich załadowaniu, a następnie zachowa je w pamięci jako nieskompresowane wartości RGBA. Tak więc format obrazu ma znaczenie tylko dla prędkości ładowania i miał miejsce na dysku (lub wykorzystanie przepustowości podczas wysyłania ich przez sieć).
źródło
Nie wiem dużo o libgdx, ale o formatach obrazów i grafice:
JPEG jest bardzo dobry w przypadku zdjęć ze świata rzeczywistego. Są stratne, ale na zdjęciach nie zobaczysz artefaktów, chyba że zrobisz zdjęcia o ostrych krawędziach z jednolitymi kolorowymi spacjami, np. Tekstem pisanym lub komiksem. Używaj ich do tworzenia dużych grafik w tle.
GIF jest przestarzały, może przechowywać tylko paletę kolorów (do 8 bitów na piksel) z jednym dedykowanym kolorem dla pełnej przejrzystości. Umożliwia małe animacje oparte na ramkach. Kiedyś istniał patent na algorytm pakowania, dzięki czemu nie można go było stosować wszędzie legalnie. Dzięki temu patentowi opracowano PNG.
PNG jest mniej więcej spakowaną bitmapą, która może przechowywać RGB + alfa (do 32 bitów) i inne formaty pikseli. Specjalizuje się w szybkim rozpakowywaniu małych części tego obrazu, co jest wygodne dla bardzo małych i wolnych urządzeń (takich jak 10-letni telefon komórkowy), ale dzisiejsze biblioteki po rozpakowaniu rozpakowują je do bitmap.
Format PNG jest lepszy niż format GIF, szybkość i funkcje, ale jeśli chcesz efektywnie przechowywać mapy bitowe, sugeruję: .PNM.BZ2 ([edycja] Ze względu na inną metodę pakowania, .PNM.BZ2 nie zawsze jest bardziej wydajny niż .PNG. [/ edit])
PNM / PBM / PGM / PAM to zwykłe formaty bitmapowe z nagłówkami KISS w postaci zwykłego tekstu. Użycie gzip na tych plikach da rozmiar pliku podobny do PNG, więc bzip2 jest lepszym rozwiązaniem. Jeśli zamierzasz używać bitmap wewnętrznie w swoim programie, możesz użyć bitmap skompresowanych bzip2 w kontenerze .tar lub .zip. Jeśli nie masz bzip2, używanie PNM w kontenerze zip (zip z maksymalną kompresją) może być podobne do używania PNG. - Tak więc przechowywanie plików PNG w pliku ZIP może mieć tylko niewielką lub żadną korzyść - najprawdopodobniej po prostu wydłuży czas ładowania obrazu.
Poza tym dobrze jest przechowywać kilka małych ikonek / obrazów w jednej mapie bitowej, szczególnie gdy potrzebujesz ich wszystkich w tej samej sytuacji razem.
źródło
Jako format przechowywania JPEG jest prawdopodobnie najlepszym wyborem dla niektórych tekstur, takich jak trawa lub ściany, gdzie utrata informacji jest prawdopodobnie niewykrywalna. Po PNG, gdy potrzebujesz przejrzystości lub gdy nie możesz zapłacić z utratą informacji, na przykład duszki w grze 2D (gracz, wrogowie, skrzynia skarbów), prawdopodobnie chcesz użyć PNG do tych obrazów.
Mówiąc o koszcie pamięci, format używany do przechowywania grafiki gry w systemie plików w ogóle nie jest istotny. Albo jeśli przechowujesz bufory pikseli w VRAM, albo RAM (renderer oprogramowania), prawdopodobnie przechowujesz je w stanie nieskompresowanym, ponieważ gry preferują szybki odczyt pikseli w porównaniu z pamięcią używaną przez każdy bufor pikseli.
Skompresowane dane przechowywane w pamięci nie mają sensu, z wyjątkiem utrzymywania pewnego rodzaju pamięci podręcznej w celu zapisywania odczytów dysku, ale prawdopodobnie musisz odczytać z tej pamięci podręcznej do stanu nieskompresowanego dla obrazów używanych w danym momencie w grze.
Skompresowane dane obrazu mają nieco większy sens, jeśli możliwe jest szybkie dekodowanie sprzętowe. Przynajmniej do normalnego mapowania pamiętam ten http://en.wikipedia.org/wiki/3Dc . Dzięki temu możesz zaoszczędzić trochę pamięci VRAM. Nie znam jeszcze innych przykładów dekodowania sprzętowego.
Wznów: niezależnie od formatów używanych w grze do przechowywania grafiki w trwałym magazynie, musisz ją zdekodować i zachować nieskompresowaną wersję w pamięci dynamicznej, pamięci wideo lub w obu, aby móc szybko renderować je w razie potrzeby.
Wreszcie: jestem facetem od komputera. Kiedy mówię „pamięć”, zawsze mam na myśli pamięć dynamiczną. Kiedy mówię „dysk”, „system plików” lub „trwała pamięć”, zawsze mam na myśli to, co urządzenie używa jako pamięć trwałą, zwykle myślę o dyskach twardych. Kiedy powiedziałeś „wydajność pamięci”, wziąłem to za „pamięć dynamiczną”, a nie „pamięć trwałą”. Ostatnio widzę wiele osób używających słowa „pamięć” w odniesieniu do „trwałego przechowywania” (może to terminologia urządzeń mobilnych?).
źródło