Format gambar mana yang lebih efisien untuk menghemat memori? PNG, JPEG, atau GIF?
graphics
graphics-programming
image
memory-efficiency
Tredecies Nocturne
sumber
sumber
Jawaban:
"Memori" dan "efisiensi" adalah istilah yang sering disalahgunakan, jadi saya akan memberi Anda jawaban untuk empat elemen berbeda yang dapat memengaruhi kinerja gim Anda.
Saya akan terlalu menyederhanakan terlalu banyak hal untuk membuatnya singkat dan ringkas, tetapi ada banyak ketidakakuratan dalam teks di bawah ini, jadi bawa dengan sejumput garam. Namun, konsep utama harus dapat dimengerti.
Penyimpanan
Ini adalah ukuran yang dikonsumsi gambar Anda pada distribusi perangkat lunak Anda. Semakin banyak ruang yang digunakan sumber daya Anda, semakin lama unduhan (seperti dari situs web Anda). Jika Anda mendistribusikan di media fisik, seperti CD atau DVD, Anda mungkin harus melakukan beberapa optimasi serius di bagian depan ini.
Secara umum, JPEG mengkompres yang terbaik untuk foto dan gambar tanpa batas yang tajam. Namun, gambar Anda akan mengalami penurunan kualitas karena JPEG menggunakan kompresi lossy (Anda dapat mengatur tingkat / degradasi kompresi saat mengekspor gambar sebagai JPEG. Lihat dokumentasi perangkat lunak pencitraan Anda untuk informasi lebih lanjut tentang ini).
Namun, sebagus JPEG mungkin, itu tidak mendukung transparansi . Ini sangat penting jika Anda ingin memiliki gambar yang ditampilkan melalui orang lain, atau jika Anda ingin gambar dengan bentuk tidak teratur. GIF adalah pilihan yang baik, tetapi sebagian besar telah digantikan oleh PNG (hanya ada beberapa hal yang GIF mendukung bahwa PNG tidak, tetapi mereka sebagian besar tidak relevan dalam pemrograman game).
PNG mendukung transparansi (dan semi transparansi), memampatkan data tanpa penurunan kualitas (yaitu menggunakan kompresi lossless), dan memampatkan dengan cukup baik, tetapi tidak sebanyak JPG.
Masalah muncul ketika Anda membutuhkan kompresi yang baik, serta transparansi. Jika Anda tidak keberatan dengan gambar yang sedikit terdegradasi, Anda dapat menggunakan program kuantisasi PNG seperti pngquant , yang dapat Anda uji online di TinyPNG . Perlu diingat bahwa degradasi gambar yang dilakukan oleh kuantisasi sendiri berbeda dari JPEG (yang mencakup kuantisasi serta teknik agresif lainnya), jadi pastikan untuk mencoba keduanya, dengan berbagai pengaturan.
Jika Anda ingin meminimalkan ukuran distribusi secara agresif, Anda dapat memproses secara manual setiap gambar seperti ini:
Tip: tidak apa-apa untuk menyimpan beberapa gambar dalam satu format, dan yang lain dalam format lain.
Ada format khusus lainnya seperti DXT, ETC dan PVRTC. Mereka mendukung kompresi, dan juga dapat dimuat dikompresi ke dalam memori, tetapi mereka hanya didukung oleh GPU tertentu, dan sebagian besar GPU ini hanya mendukung salah satunya, jadi kecuali Anda tahu spesifikasi perangkat keras yang tepat dari perangkat keras target Anda (kasus penting adalah iPhone / iPad, yang mendukung tekstur PVRTC), Anda harus menghindari format ini.
Memori Program
Saya memasukkannya di sini, karena ini adalah yang biasa dikenal dengan "memori". Namun, jika game Anda menggunakan akselerasi grafis (dan jika Anda membuat game setelah 1998, kemungkinan besar Anda adalah), maka satu-satunya hal yang akan mengkonsumsi memori adalah deskriptor tekstur Anda (hanya beberapa byte per gambar), yang hanya dipengaruhi oleh jumlah gambar, dan bukan ukuran atau formatnya (ini memiliki beberapa peringatan, tetapi sebagian besar tidak relevan).
Jika platform Anda tidak memiliki memori video khusus, tidak dipercepat perangkat keras, atau kasus tidak umum lainnya, maka bagian selanjutnya tentang VRAM akan terjadi sepenuhnya atau sebagian dalam RAM, tetapi prinsip-prinsip utama akan sama.
Memori video
Di sinilah gambar Anda akan disimpan setelah program Anda berjalan. Secara umum, format penyimpanan Anda tidak akan membuat perbedaan di sini, karena semua gambar didekompresi sebelum memuatnya ke dalam memori video.
Sekarang, VRAM yang dikonsumsi oleh gambar Anda kira-kira akan
width * height * bitdepth
untuk setiap gambar yang dimuat dalam VRAM. Ada beberapa hal yang perlu diperhatikan di sini:Lebar dan tinggi penyimpanan gambar Anda di VRAM tidak akan sama dengan gambar asli Anda. Beberapa GPU hanya dapat menangani tekstur dengan ukuran dalam kekuatan 2, sehingga gambar 320x240 Anda sebenarnya dapat disimpan dalam ruang 512x256 dalam VRAM, dengan memori yang tidak digunakan terbuang secara efektif. Beberapa kali Anda bahkan tidak diizinkan memuat tekstur dengan ukuran yang bukan kekuatan 2 (seperti di GLES 1.1).
Jadi jika Anda ingin meminimalkan penggunaan VRAM, Anda mungkin ingin mempertimbangkan untuk menghapus gambar Anda, dan mengukurnya dengan kekuatan 2, yang juga akan memiliki keuntungan lebih sedikit perubahan status render saat rendering. Lebih lanjut tentang ini nanti.
Bitdepth sangat penting. Biasanya tekstur dimuat ke VRAM dalam 32-bit ARGB atau 32-bit XRGB, tetapi jika perangkat keras Anda dapat mendukung kedalaman 16-bit, dan Anda tidak keberatan memiliki bitdepth yang lebih rendah, Anda dapat setengah jumlah VRAM yang dikonsumsi oleh setiap gambar , yang mungkin sesuatu yang menarik untuk dipertimbangkan.
Namun apa pun yang Anda lakukan, faktor terpenting ketika mempertimbangkan jumlah VRAM yang digunakan game Anda, adalah jumlah gambar yang Anda miliki di VRAM pada waktu tertentu. Ini adalah angka yang kemungkinan besar ingin Anda tetap serendah mungkin jika Anda ingin permainan yang berkinerja baik. Memuat dan menurunkan tekstur ke dalam VRAM itu mahal, jadi Anda tidak bisa hanya memuat setiap gambar kapan pun Anda akan menggunakannya. Anda harus menemukan keseimbangan antara preloading gambar yang kemungkinan besar akan Anda gunakan, dan keluarkan ketika Anda yakin Anda tidak akan menggunakannya lagi. Melakukan ini dengan benar bukanlah hal yang sepele, dan Anda harus memikirkan strategi Anda sendiri untuk gim khusus Anda.
Kecepatan eksekusi
Meskipun bukan "memori", ini sangat terkait dengan kinerja dalam game. Menggambar gambar itu mahal, dan Anda ingin memastikan rendering Anda berjalan secepat mungkin. Tentu saja, di sini, format tidak masalah, tetapi hal-hal lain berlaku:
Ukuran gambar (sebenarnya, itu akan menjadi "ukuran sampel"): semakin besar wilayah gambar yang akan Anda gambar, semakin banyak waktu yang dibutuhkan untuk menggambarnya. Rendering gambar besar di bagian kecil layar tidak terlalu efektif, sehingga ada teknik yang disebut mipmapping , yang terdiri dari perdagangan VRAM untuk kecepatan rendering, dengan menyimpan gambar Anda beberapa kali di beberapa resolusi dan menggunakan yang terkecil yang dapat memberikan Anda kualitas yang diperlukan pada waktu tertentu. Pemetaan dapat dilakukan ketika gambar dimuat, yang akan berdampak pada kecepatan pemuatan dan penggunaan VRAM, atau pada preprocessing (dengan secara manual menyimpan versi berbeda dari gambar yang sama, atau menggunakan format yang mendukung pemetaan asli seperti DDS), yang akan berdampak pada penyimpanan dan penggunaan VRAM, tetapi akan berdampak kecil pada kecepatan pemuatan.
Status render berubah. Anda kemungkinan besar ingin menggambar beberapa gambar berbeda di layar secara bersamaan. Namun, GPU hanya dapat menggunakan gambar sumber tunggal pada waktu tertentu (ini tidak benar, tapi tolong tahan dengan saya di sini). Gambar yang saat ini digunakan untuk rendering adalah salah satu dari banyak negara render , dan harganya mahal. Jadi jika Anda akan menggunakan gambar yang sama beberapa kali (ingat ketika saya menyebutkan atlas tekstur ?), Anda akan melihat peningkatan kinerja yang sangat besar jika Anda menggunakan kembali gambar sebanyak yang Anda bisa sebelum Anda mengubah status render dan mulai menggunakan gambar yang berbeda (ada negara render lain yang terpisah dari ini, dan menyesuaikan urutan di mana Anda menggambar barang-barang Anda untuk meminimalkan perubahan keadaan render adalah aktivitas yang sangat umum ketika meningkatkan kinerja permainan)
Namun , pengoptimalan penggunaan gambar adalah topik yang sangat kompleks, dan apa yang saya tulis di sini adalah gambaran yang sangat luas dan disederhanakan dari beberapa faktor yang harus Anda pertimbangkan saat menulis gim, jadi saya pikir itu yang terbaik jika Anda membuatnya sederhana, dan hanya mengoptimalkan setiap kali Anda benar-benar perlu melakukannya. Sebagian besar waktu, pengoptimalan prematur tidak perlu (dan kadang-kadang bahkan merugikan), jadi tenang saja.
sumber
setEnforcePotImages
, itu menonaktifkan penegakan kekuatan 2 ukuran tekstur untuk OpenGLES 1.0. Ini bukan ide yang baik, karena tidak semua perangkat keras mendukung tekstur non-power-of-2. OpenGLES 2.0 membutuhkan dukungan untuk tekstur non-power-of-2, jadi jika Anda menargetkan 2.0, Anda dapat menggunakan tekstur dari berbagai ukuran. Untuk informasi lebih lanjut lihat dokumentasi libgdx.Setelah gambar dimuat dari disk dan diformat untuk rendering, itu akan menggunakan jumlah memori yang sama terlepas dari apakah gambar itu disimpan ke disk menggunakan PNG, JPEG, atau GIF.
Aturan umum: JPEG adalah format lossy, dan akan menurunkan kualitas gambar untuk membuat gambar lebih kecil pada disk. PNG, di sisi lain, adalah format gambar lossless, dan biasanya akan menghasilkan ukuran file yang lebih besar pada disk. GIF juga secara teknis merupakan format lossless, tetapi hanya mendukung maksimum 256 warna per gambar, sehingga gambar berwarna tinggi akan sering mengalami kehilangan kualitas yang besar jika disimpan sebagai GIF.
Itu hanya untuk representasi on-disk mereka. Dalam memori, keduanya akan berkembang ke format tekstur yang sama, menggunakan jumlah memori yang sama, terlepas dari apakah Anda menyimpannya ke disk sebagai PNG, atau sebagai JPEG, atau sebagai GIF.
sumber
Tergantung.
Jpeg paling efisien untuk foto. Ini bukan lossless, tetapi artefak yang diperkenalkan oleh kompresi paling tidak terlihat dalam kasus penggunaan ini.
PNG adalah lossless dan paling efisien untuk pixel-art dengan garis-garis tajam dan beberapa warna. Ini juga mendukung transparansi alpha.
GIF tidak bisa melakukan apa pun PNG tidak bisa berbuat lebih baik, kecuali kemampuannya untuk menyimpan animasi. Tetapi ini hanya relevan dalam konteks aplikasi web. Dalam pengembangan game, Anda biasanya membuat animasi dengan menggunakan spritesheet.
Perhatikan bahwa ketika Anda menggunakan mesin grafis seperti Libgdx, itu kemungkinan besar akan mengompres gambar setelah memuatnya dan kemudian menyimpannya dalam memori sebagai nilai-nilai RGBA yang tidak terkompresi. Jadi format gambar hanya penting untuk kecepatan memuat dan memiliki ruang drive (atau penggunaan bandwidth saat Anda mengirimnya melalui internet).
sumber
Saya tidak tahu banyak tentang libgdx, tetapi tentang format gambar dan grafik:
JPEG sangat bagus dalam hal foto dunia nyata. Mereka merugi tetapi Anda tidak akan melihat artefak pada foto kecuali jika Anda mengambil gambar tepi tajam dengan ruang berwarna polos, seperti misalnya teks atau komik tertulis. Gunakan mereka untuk grafik latar belakang yang besar.
GIF sudah usang, ia hanya dapat menyimpan warna yang dipalpasi (hingga 8 bit per piksel) dengan satu warna khusus untuk transparansi lengkap. Ini memungkinkan animasi kecil berdasarkan bingkai. Pernah ada paten pada algoritma pengemasannya sehingga tidak bisa digunakan di mana-mana secara legal. Karena paten itu, PNG dikembangkan.
PNG kurang lebih merupakan bitmap zip yang dapat menyimpan RGB + alpha (hingga 32bit) dan format piksel lainnya. Ini adalah khusus untuk membuka ritsleting cepat dari bagian-bagian kecil dari gambar itu, yang nyaman untuk perangkat yang sangat kecil dan lambat (seperti ponsel 10 tahun), tetapi perpustakaan saat ini hanya membongkar mereka ke bitmap ketika dimuat.
PNG lebih baik daripada GIF dalam ukuran dan kecepatan serta fitur, tetapi jika Anda ingin menyimpan bitmap secara efisien, saya sarankan: .PNM.BZ2 ([sunting] Karena metode pengemasan yang berbeda, .PNM.BZ2 tidak selalu lebih efisien dari .PNG. [/ edit])
PNM / PBM / PGM / PAM adalah format bitmap biasa dengan header KISS dalam teks biasa. Menggunakan gzip pada mereka akan menghasilkan ukuran file yang mirip dengan PNG, jadi bzip2 adalah solusi yang lebih baik untuk itu. Jika Anda akan menggunakan bitmap secara internal dalam program Anda, Anda mungkin ingin menggunakan bitmap bzip2 terkompresi dalam wadah .tar atau .zip. Jika Anda tidak memiliki bzip2, menggunakan PNM dalam wadah zip (zip dengan kompresi maksimum) mungkin mirip dengan menggunakan PNG. - Jadi, menyimpan PNG dalam file ZIP mungkin hanya memiliki manfaat kecil atau tidak sama sekali - kemungkinan besar hanya akan menambah waktu untuk memuat gambar.
Selain itu, itu adalah pilihan yang baik untuk menyimpan beberapa sprite / gambar kecil dalam satu bitmap, terutama ketika Anda membutuhkan semuanya dalam situasi yang sama.
sumber
Karena format penyimpanan, JPEG mungkin merupakan pilihan terbaik untuk beberapa tekstur seperti rumput atau dinding, di mana hilangnya informasi mungkin tidak terdeteksi. Diikuti oleh PNG ketika Anda membutuhkan transparansi atau ketika Anda tidak dapat membayar dengan kehilangan informasi, misalnya sprite dalam game 2D (pemain, musuh, peti harta karun), Anda mungkin ingin menggunakan PNG untuk gambar itu.
Ketika berbicara tentang biaya memori, format yang digunakan untuk menyimpan grafik game dalam sistem file tidak relevan sama sekali. Baik jika Anda menyimpan penyangga piksel dalam VRAM, atau RAM (peranti lunak peranti lunak), Anda mungkin menyimpan penyimpannya tanpa kompresi, karena gim mendukung pembacaan cepat piksel dan memori yang digunakan oleh setiap penyangga piksel.
Memiliki data terkompresi yang disimpan dalam memori tidak masuk akal kecuali Anda mempertahankan beberapa jenis cache untuk menyimpan membaca disk, tetapi Anda mungkin harus membaca dari cache itu ke keadaan tidak terkompresi untuk gambar yang digunakan pada waktu tertentu dalam gim Anda.
Data gambar yang dikompresi memiliki lebih banyak akal jika decoding perangkat keras yang cepat dimungkinkan. Setidaknya untuk pemetaan normal, saya ingat ini http://en.wikipedia.org/wiki/3Dc . Dengan itu Anda dapat menyimpan beberapa VRAM. Saya belum mengetahui contoh lain dari decoding perangkat keras.
Dalam resume: apa pun format yang digunakan untuk gim Anda untuk menyimpan grafik dalam penyimpanan yang persisten, Anda harus memecahkan kode itu dan mempertahankan versi yang tidak terkompresi dalam memori dinamis, memori video, atau keduanya, agar dapat dengan cepat merendernya saat diperlukan.
Akhirnya: Saya seorang pria desktop. Ketika saya mengatakan "memori" saya selalu mengacu pada memori dinamis. Ketika saya mengatakan "disk", "sistem file" atau "penyimpanan persisten", saya selalu merujuk pada apa pun yang digunakan perangkat Anda sebagai penyimpanan persisten, biasanya saya pikir dalam hard disk. Ketika Anda mengatakan "efisiensi memori" saya mengambilnya untuk "memori dinamis" bukan "penyimpanan persisten". Akhir-akhir ini, saya melihat banyak orang menggunakan kata "memori" untuk merujuk ke "penyimpanan persisten" (mungkin itu terminologi perangkat seluler?).
sumber