Hangi görüntü formatı daha verimli bellek kullanır: PNG, JPEG veya GIF?


Yanıtlar:


153

"Bellek" ve "verimlilik" genel olarak kötüye kullanılan terimlerdir, bu yüzden size oyununuzun performansını etkileyebilecek dört farklı öğeye cevap vereceğim.

Kısa ve özlü tutmak için çok fazla şeyi aşırı basitleştireceğim, ancak bu metinde tonlarca yanlışlık var, bu yüzden bir tutam tuzla alın. Ancak, ana kavramlar anlaşılabilir olmalıdır.

Depolama

Bu, resimlerinizin yazılım dağıtımınızda kullandığı boyuttur. Kaynaklarınız ne kadar fazla yer kaplarsa, indirme (web sitenizden olduğu gibi) o kadar uzun olacaktır. CD veya DVD gibi fiziksel ortamlara dağıtıyorsanız, muhtemelen bu cephede bazı ciddi optimizasyonlar yapmanız gerekecektir.

Genel olarak, JPEG keskin sınırları olmayan fotoğraflar ve görüntüler için en iyi olanı sıkıştırır. Ancak, JPEG, kayıplı sıkıştırma kullandığından görüntü kalitesinin düşmesine neden olacaktır (görüntüleri JPEG olarak dışa aktarırken sıkıştırma seviyesini / bozulmasını ayarlayabilirsiniz. Bu konuda daha fazla bilgi için görüntüleme yazılımınızın belgelerine bakın).

Ancak, JPEG olabildiğince iyi, saydamlığı desteklemiyor . Başkalarının içinden geçen görüntülere sahip olmak veya düzensiz şekilli görüntülere sahip olmak istiyorsanız, bu çok önemlidir. GIF iyi bir seçimdir, ancak PNG tarafından büyük ölçüde yerine getirildi (GIF'in PNG'nin desteklemediği birkaç şey var, ancak oyun programlamasında büyük önemsizler).

PNG, saydamlığı (ve yarı saydamlığı) destekler, kaliteyi bozmadan verileri sıkıştırır (yani kayıpsız sıkıştırma kullanır) ve JPG kadar değil, oldukça iyi sıkıştırır.

Sorun, saydamlığın yanı sıra iyi bir sıkıştırmaya ihtiyaç duyduğunuzda ortaya çıkar. Biraz bozulmuş resimlere aldırış etmiyorsanız , çevrimiçi olarak TinyPNG'de test edebileceğiniz pngquant gibi PNG miktarlandırma programlarını kullanabilirsiniz . Kendi kendine nicelemeyle yapılan görüntü bozulmasının JPEG'inkinden farklı olduğunu unutmayın (ki bu, diğer agresif tekniklerin yanı sıra nicelemeyi de içerir);

Dağıtım boyutunuzu agresif bir şekilde küçültmek istiyorsanız, aşağıdaki gibi her görüntüyü manuel olarak işleyebilirsiniz:

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

İpucu: Bazı görüntüleri tek bir formatta, diğerlerini başka bir formatta saklamak iyidir.

DXT, ETC ve PVRTC gibi başka özel biçimler de vardır. Sıkıştırmayı desteklerler ve ayrıca belleğe sıkıştırılmış olarak da yüklenebilirler, ancak yalnızca belirli GPU'lar tarafından desteklenirler ve bu GPU'ların çoğu yalnızca birini desteklemektedir, bu nedenle hedef donanımınızın tam donanım özelliklerini bilmiyorsanız (dikkate değer bir durum PVRTC dokularını destekleyen iPhone / iPad), bu formatlardan kaçınmalısınız.

Program hafızası

Buraya dahil ettim, çünkü yaygın olarak "hafıza" olarak bilinen şey bu. Ancak, oyununuz grafik hızlandırmayı kullanıyorsa (ve 1998'den sonra bir oyun yapıyorsanız, büyük olasılıkla vardır), o zaman hafıza tüketen tek şey doku tanımlayıcılarınızdır (görüntü başına sadece birkaç bayt), bu sadece görüntülerin miktarından etkilenir , boyutlarına veya biçimlerine değil (bunun birkaç uyarısı vardır, ancak çoğunlukla ilgisizdir).

Platformunuzda özel video belleği yoksa, donanım hızlandırması veya nadir görülen durumlar yoksa, VRAM ile ilgili bir sonraki bölüm tamamen veya kısmen RAM'de gerçekleşecek, ancak ana prensipler aynı olacaktır.

Video belleği

Burası programınız çalıştığında resimlerinizin depolanacağı yerdir. Genel olarak, içinde sakladığınız format burada fark yaratmaz, çünkü tüm görüntüler video belleğine yüklenmeden önce sıkıştırılır.

Artık, resimleriniz tarafından tüketilen VRAM, VRAM'a yüklenen width * height * bitdepth her resim için kabaca olacaktır . Burada dikkat edilmesi gereken birkaç şey var:

  1. Görüntülerin VRAM'da saklandığı genişlik ve yükseklik, mutlaka orijinal görüntünüzünkilerle eşleşmeyecektir. Bazı GPU'lar yalnızca 2 boyutundaki dokulara sahip dokuları kullanabilir, bu nedenle 320x240 görüntünüz VRAM'de 512x256 alanda ve kullanılmayan bellek etkin bir şekilde boşa harcanabilir. Bazı zamanlar 2'nin gücü olmayan boyutta doku yüklemenize bile izin verilmez (GLES 1.1'de olduğu gibi).

    Bu nedenle, VRAM kullanımını en aza indirmek istiyorsanız , resimlerinizi atlatmayı ve bunları 2 güçleriyle boyutlandırmayı düşünebilirsiniz ; bu, oluşturma sırasında daha az oluşturma durumu değişikliği avantajına da sahip olur. Bunun üzerine daha sonra.

  2. Bit hızı çok önemlidir. Genellikle dokular 32 bit ARGB veya 32 bit XRGB’de VRAM’e yüklenir, ancak donanımınız 16 bit derinlikleri destekliyorsa ve bit bit hızının düşük olmasını önemsemiyorsanız, her görüntü tarafından tüketilen VRAM miktarının yarısını , dikkate alınması gereken ilginç bir şey olabilir.

  3. Ancak ne yaparsanız yapın, oyununuzun kullandığı VRAM miktarını göz önünde bulundururken en önemli faktör, VRAM'da verilen görüntülerin miktarıdır . İyi bir performans sergileyen bir oyun istiyorsanız, mümkün olduğu kadar düşük tutmak isteyebileceğiniz sayı budur. Dokuları VRAM'a yüklemek ve boşaltmak pahalıdır, bu nedenle kullanacağınız her görüntüyü yalnızca yükleyemezsiniz. Büyük olasılıkla kullanacağınız görüntülerin önceden yüklenmesi ve artık kullanmayacağınızdan emin olduğunuzda bunları boşaltmanız arasında bir denge kurmanız gerekir. Bu hakkı yapmak önemsiz değildir ve kendi oyununuz için kendi stratejinizi düşünmeniz gerekir.

Yürütme hızı

“Hafıza” olmasa da, oyunlardaki performansla çok ilgili. Görüntüleri çizmek pahalıdır ve oluşturma işleminizin olabildiğince hızlı çalıştığından emin olmak istersiniz. Elbette, burada, format önemli değil, fakat başka şeyler de var:

  1. Görüntü boyutu (aslında, "örnekleme boyutu" olur): Bir resmin çizeceği bölge en büyük, çizilmesi gereken süre o kadar fazla olur. Ekranın küçük bir bölümünde büyük bir görüntüyü oluşturmak çok etkili değildir; bu nedenle , görüntülerinizi birkaç kez saklayarak ve en düşük çözünürlükte kullanarak görüntülerini hızlandıran VRAM'den oluşan mipmapping adı verilen bir teknik vardır. herhangi bir zamanda istediğiniz kalitede size. Görüntüler yüklendiğinde, yükleme hızını ve VRAM kullanımını etkileyebilecek veya ön işleme sırasında (aynı görüntünün farklı sürümlerini elle depolayarak veya depolamayı etkileyecek DDS gibi mipmaplamayı doğal olarak destekleyen bir format kullanarak), mipmap oluşturma gerçekleştirilebilir ve VRAM kullanımı, ancak yükleme hızı üzerinde çok az etkisi olacaktır.

  2. Render durum değişiklikleri. Aynı anda ekranda birkaç farklı görüntü çizmek isteyeceksiniz. Ancak, GPU herhangi bir zamanda yalnızca tek bir kaynak görüntü kullanabilir (bu doğru değildir, ancak lütfen burada benimle birlikte hareket edin). Oluşturma için şu anda kullanılan resim birçok biridir hale devletler ve pahalıdır. Bu yüzden, aynı görüntüyü birkaç kez kullanacaksanız ( doku atlaslarından bahsettiğimde hatırlıyor musunuz?), Görüntü oluşturma durumunu değiştirmeden ve kullanmaya başlamadan önce görüntüyü olabildiğince tekrar kullanırsanız büyük bir performans kazancı fark edeceksiniz. farklı görüntü (bunun dışında başka oluşturma durumları da vardır ve oluşturma durumu değişikliklerini en aza indirmek için eşyalarını çizdiğiniz sıraya göre ince ayar yapmak bir oyunun performansını artırırken çok yaygın bir etkinliktir)

Bununla birlikte , görüntü kullanımı optimizasyonu çok karmaşık bir konudur ve burada yazdıklarım, bir oyun yazarken göz önünde bulundurmanız gereken bazı faktörlere ilişkin çok geniş ve basitleştirilmiş bir genel bakış; ve sadece gerçekten yapmanız gerektiğinde optimize edin. Önceden optimize etmek çoğu zaman gereksizdir (ve hatta bazen zararlıdır), bu yüzden kolay.


25
+1. Bu, çok fazla zemini kapsayan oldukça kapsamlı bir cevap. Doku tanımlayıcılarının boyutunun sahip olduğu kadar fazla alana ihtiyaç duyduğundan emin değilim ve DXT / ETC / PVRTC'nin bahsettiği, gerçekten sadece her birinin bazı platformlarda çalıştığını içermelidir - platformlar arası açık değillerdir. Her yerde kullanılabilen standartlar, JPEG, PNG ve GIF formatları. Ama genel olarak, çok etkilendim. Bu, cevabımın üstünde "küçük bir açıklama" dan çok daha fazlası! : D
Trevor Powell

9
@PandaPajama: Belki de değil, ama bu sorunun hakettiğinden şaşırtıcı derecede daha iyi bir cevap.
Marcks Thomas

1
+1, ve yapabilseydim daha fazlası. Bu harika bir cevaptır ve “bellek verimliliği” ile ilgili herhangi bir soru için standart bir referans noktası olmalıdır, çünkü daha az bellek kullanmanın sadece görüntüler için değil, her zaman en iyi yaklaşım olduğu ortak efsaneye karşı çıkarıyor. Eklemek istediğim bir şey, hızlandırılmış olmayan durumda, çizim sırasında herhangi bir anında dekompresyona ihtiyaç duyulması halinde, kabul edilemez bir performans ek yüküne yol açabileceğidir.
Maximus Minimus

2
PNGGauntlet'i önermek istiyorum . PNG dosya boyutları için, özellikle çok sayıda sprite olduğunda ekleyebileceğiniz devasa kayıpsız optimizasyonlar yapabilir. Ne yazık ki sadece Windows, ancak alternatifler diğer işletim sistemlerinde ana sayfada listelenmiştir.
orlp

1
@DavidDimalanta libgdx ile hiçbir deneyimim yok, ancak belgelerinin de görebileceği gibi, OpenGLES setEnforcePotImages1.0 için 2 boyutlu dokunun gücünün uygulanmasını engelliyor . Bu iyi bir fikir değil, çünkü tüm donanım 2 güçten arındırılmış dokuları desteklemiyor. OpenGLES 2.0 2 güçlü olmayan dokular için destek gerektirir, böylece 2.0'ı hedefliyorsanız, istediğiniz boyutta dokular kullanabilirsiniz. Daha fazla bilgi için libgdx belgelerine bakın.
Panda Pajama

26

Bir görüntü diskten yüklenip oluşturma için biçimlendirildikten sonra, o görüntünün PNG, JPEG veya GIF kullanılarak diske kaydedilmesine bakılmaksızın aynı miktarda bellek kullanır.

Genel kural: JPEG kayıplı bir formattır ve görüntüyü diskte küçültmek için görüntü kalitesini düşürür. PNG, diğer taraftan, kayıpsız bir görüntü formatıdır ve bu nedenle genellikle diskte daha büyük dosya boyutlarına neden olur. GIF ayrıca teknik olarak kayıpsız bir formattır, ancak görüntü başına yalnızca maksimum 256 rengi destekler ve bu nedenle yüksek renkli bir görüntü, GIF olarak kaydedildiğinde genellikle ağır kalite kaybına neden olur.

Ancak bu onların yalnızca diskteki temsili için. Bellekte, PNG olarak mı yoksa JPEG olarak mı yoksa GIF olarak mı kaydettiğinizden bağımsız olarak, aynı miktarda bellek kullanarak aynı doku biçiminde genişlerler.


Yani bu bellek boyutunu değiştiren dosya uzantısı değil, dosya boyutunu?
Tredecies Nocturne,

Ne. Bellekteki boyut, görüntü boyutlarına ve bit hızına dayanır. Görüntü ekrana çekilmek üzere görüntü belleğe yüklendiğinde görüntü dosyasındaki tüm sıkıştırma kaldırılır. (Çünkü GPU'lar PNG'leri veya JPEG'leri veya benzeri şeyleri oluşturamazlar. Görüntüler GPU'ların onlarla başa çıkabilmesi için genel pixmap'lere genişletilir.)
Trevor Powell

2
Bu% 100 doğru değil. Çoğu modern GPU (gömülü olanlar dahil), sıkıştırılmış dokuların grafik belleğine yüklenmesini ve saklanmasını destekler; DXT, ETC ve PVRTC gibi formatlar gömülü dünyada en yaygın olanıdır. Elbette, dokularınızı PNG / JPG / GIF yerine bu formatlarda ilk etapta saklamanız gerekir.
Panda Pajama

6
Soru PNG / JPG / GIF arasında açık bir seçimdi ve bunların hiçbiri bilmediğim herhangi bir GPU'da doğal olarak desteklenmiyordu. Asıl soru sahibi, diskteki dosya boyutu ile RAM'deki boş alan arasındaki ayrım konusunda yeterince sorun yaşıyordu, daha fazla dosya formatı eklemenin sadece asıl meseleyi karıştıracağını düşündüm. Yine de kendi cevabınızı vermekten çekinmeyin.
Trevor Powell,

2
Benim yorumum sadece bir açıklamadır. Bir cevap verseydim, büyük ihtimalle sizin de yaptığınız gibi yazmış olurdum, ayrıca yorumumu nihai bir kapanış ifadesi olarak yazdım. Ekleyecek başka bir şeyim yok, bu yüzden kendi cevabımı sağlayarak tekrar etmekten kaçınacağım.
Panda Pajama

3

Değişir.

Jpeg, fotoğraflar için en verimli olanıdır. Kayıpsız değildir, ancak bu kullanım durumunda sıkıştırmanın neden olduğu eserler en az görülebilir.

PNG, keskin çizgiler ve az renkli pikseller için kayıpsız ve en verimli olanıdır. Aynı zamanda alfa saydamlığını da destekler.

GIF, PNG'nin daha iyi yapamayacağı bir şey yapamaz, animasyonları saklayabilmesi dışında. Ancak bu sadece web uygulamaları bağlamında geçerlidir. Oyun geliştirmede genellikle bir spritesheet kullanarak animasyonlar yaratırsınız.

Libgdx gibi bir grafik motoru kullandığınızda, görüntüleri yükledikten hemen sonra açacağınızı ve ardından sıkıştırılmamış RGBA değerleri olarak bellekte tutacağını unutmayın. Bu nedenle, görüntü formatı yalnızca yükleme hızı için önemlidir ve sürücü alanı (veya ağ üzerinden gönderdiğinizde bant genişliği kullanımı) vardır.


2

Libgdx hakkında değil, resim biçimleri ve grafikler hakkında çok fazla bilgim yok:

JPEG, gerçek dünya fotoğrafları için çok iyidir. Kayıplıdırlar, örneğin yazılı metin veya çizgi roman gibi düz renkli alanlarda keskin kenarların resimlerini çekmediğiniz sürece fotoğraflarda eserler görmezsiniz. Büyük arka plan grafikleri için bunları kullanın.

GIF eskidir, tam saydamlık için yalnızca özel renkle paletlenmiş renkleri (piksel başına 8 bit'e kadar) depolayabilir. Çerçevelere dayalı küçük animasyonlara izin verir. Bir zamanlar ambalaj algoritmasında patent vardı, böylece yasal olarak her yerde kullanılamazdı. Bu patent nedeniyle PNG geliştirilmiştir.

PNG, RGB + alpha (32bit'e kadar) ve diğer piksel biçimlerini depolayabilen sıkıştırılmış bir bitmap aşağı yukarı hareket eder. Çok küçük ve yavaş cihazlar (10 yaşında bir cep telefonu gibi) için uygun olan bu resmin küçük parçalarının hızla açılması için uzmanlaşmıştır, ancak günümüz kütüphaneleri yüklendiklerinde bunları bitmaplere kadar açmaktadır.

PNG, boyut ve hız ve özelliklerde GIF'den daha iyidir, ancak bitmapleri verimli bir şekilde saklamak istiyorsanız, şunu önerebilirim: .PNM.BZ2 ([değiştir] Farklı paketleme yöntemi nedeniyle, .PNM.BZ2 her zaman daha verimli değildir .PNG'den [[değiştir])

PNM / PBM / PGM / PAM , düz metin halinde KISS başlıklı düz bitmap formatlarıdır. Bunlarda gzip kullanmak PNG'ye benzer bir dosya boyutuna neden olacaktır, bu nedenle bzip2 bunun için daha iyi bir çözümdür. Programınızda dahili olarak bitmap'ler kullanacaksanız, bir .tar veya .zip kabında bzip2 sıkıştırılmış bitmap'ler kullanmak isteyebilirsiniz. Bzip2'niz yoksa, PNM'leri bir zip kabında (maksimum sıkıştırmalı zip) kullanmak PNG'leri kullanmaya benzer olabilir. - PNG'leri ZIP dosyasına kaydetmenin çok küçük bir faydası olabilir veya faydası olmayabilir - büyük olasılıkla görüntünün yüklenme süresini uzatacaktır.

Bunun yanında, birkaç küçük sprite / resmi bir bitmapte, özellikle hepsine aynı durumda birlikte ihtiyaç duyduğunuzda saklamak için iyi bir seçimdir.


PNM dosyası mevcut ve tüm akıllı telefon işletim sistemlerinde ve masaüstü bilgisayar işletim sistemlerinde okunabilir mi?
David Dimalanta

1
@David Dimalanta: Nerede desteklendiğini ve nerede desteklendiğini bilmiyorum. PNM'lerle programlamak istiyorsanız, nadiren herhangi bir kütüphane kullanmak istersiniz, çünkü bu biçim herhangi bir API'yi seçmek için çok basittir. Bu nedenle, ikili dosyaları okuma / yazma özelliğini destekleyen mevcut tüm programlama dilleri ile okunabilir ve yazılabilir. Tabii ki Netpbm'i sadece Unix'te değil, herhangi bir işletim sisteminde de kullanabilirsiniz. Öte yandan, hangi genel resim kütüphanelerinin bunu desteklemediğini bilmiyorum. Sıkıştırılmış bir format değildir, bu nedenle görüntüleri yine de diskte depolamak için nadiren kullanılır. bkz. en.wikipedia.org/wiki/Netpbm_format
comonad

1

Depolama formatı olarak JPEG, bilgi kaybının muhtemelen tespit edilemeyeceği çim veya duvar gibi bazı dokular için en iyi seçimdir. Saydamlığa ihtiyacınız olduğunda veya bilgi kaybıyla ödeme yapamadığınızda PNG tarafından takip edilir, örneğin 2D bir oyuna (oyuncu, düşmanlar, bir hazine sandığı) yazılır, muhtemelen bu görüntüler için PNG kullanmak istersiniz.

Hafıza maliyeti hakkında konuşurken, oyun grafiklerini dosya sisteminde saklamak için kullanılan format hiç önemli değildir. Ya piksel arabelleklerini VRAM'da ya da RAM'de (yazılım oluşturucu) saklarsanız, büyük olasılıkla sıkıştırılmamış olarak depolanmış olmalarını sağlarsınız;

Bellekte depolanan sıkıştırılmış verilerin disk okumalarını kaydetmek için bir tür önbellek bulundurmanız dışında bir anlamı yoktur, ancak oyununuzda belirli bir zamanda kullanılan görüntüler için bu önbellekten sıkıştırılmamış bir duruma okumak zorundasınızdır.

Hızlı donanım kod çözme mümkün olduğunda, sıkıştırılmış görüntü verileri biraz daha anlamlı olur. En azından normal haritalama için bunu http://en.wikipedia.org/wiki/3Dc hatırlıyorum . Bununla VRAM tasarruf edebilirsiniz. Henüz diğer donanım kod çözme örneklerinden haberdar değilim.

Özgeçmiş: Oyununuz için grafikleri kalıcı depolamada saklamak için kullanılan formatlar ne olursa olsun, gerektiğinde hızlı bir şekilde görüntüleyebilmek için dinamik hafıza, video belleği veya her ikisinde sıkıştırılmamış bir versiyonun kodunu çözmeniz ve korumanız gerekecektir.

Sonunda: Ben bir masaüstü adamıyım. "Bellek" derken her zaman dinamik belleğe atıfta bulunurum. "Disk", "dosya sistemi" veya "kalıcı depolama" deyince, cihazınızın her zaman kalıcı depolama olarak kullandığı her bir şeyi kastediyorum, genellikle sabit disklerde düşünüyorum. "Hafıza verimliliği" derken, "kalıcı hafıza" değil "dinamik hafıza" için kullandım. Son zamanlarda "kalıcı depolama" ("mobil cihazların terminolojisi" anlamına gelir) için "hafıza" kelimesini kullanan bir çok insan görüyorum.


JPEG ya da PNG'nin belleği değil dosya boyutunu etkilemesi de mümkün mü?
Tredecies Nocturne,

Evet. Disk alanı veya bant genişliğinden tasarruf etmeyi düşündüğünüzde tartışılan formatlardan herhangi birini seçeceksiniz. Görüntüleri oyuna yüklerken, bildiğim herhangi bir kütüphane / motor onları sıkıştırılmamış piksel tamponlarına şifresini çözecektir (piksel tamponlarında RGB veya RGBA değerleri dizisi olarak düşünün, burada her kanal genellikle 32 bit kullanıyorsa RAM / VRAM'da 1 Bayt kaplar) piksel, muhtemelen herkesin yaptığı budur).
Hatoru Hansou
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.