Який формат зображення більш ефективний у пам’яті: PNG, JPEG або GIF?


Відповіді:


153

"Пам'ять" та "ефективність" - це звичайно зловживані терміни, тому я дам вам відповідь на чотири різні елементи, які можуть вплинути на ефективність вашої гри.

Я буду надто спрощувати занадто багато речей, щоб зробити його коротким і стислим, але в цьому тексті нижче є багато неточностей, тому візьміть це з дрібкою солі. Однак основні поняття повинні бути зрозумілими.

Зберігання

Це розмір, який ваші зображення споживають у вашому розповсюдженні програмного забезпечення. Чим більше місця займають ваші ресурси, тим довше буде завантаження (як з вашого веб-сайту). Якщо ви поширюєте на фізичних носіях, таких як компакт-диски чи DVD-диски, вам, мабуть, доведеться зробити серйозні оптимізації на цьому фронті.

Взагалі, JPEG стискає найкраще для фотографій та зображень без різких меж. Однак ваші зображення будуть погіршувати якість, оскільки JPEG використовує стиснення втрат (ви можете точно настроїти рівень / стиснення при експорті зображень у форматі JPEG. Докладнішу інформацію про це див. У документації програмного забезпечення для зображень).

Однак, наскільки JPEG хороший, він не підтримує прозорість . Це дуже важливо, якщо ви хочете мати зображення, які відображаються через інших, або якщо ви хочете зображень неправильної форми. GIF - хороший вибір, але його значною мірою витіснив PNG (є лише декілька речей, які підтримує GIF, що PNG не робить, але вони в значній мірі не мають значення в ігровому програмуванні).

PNG підтримує прозорість (і напівпрозорість), стискає дані без погіршення якості (тобто використовує стиснення без втрат) і стискає досить добре, але не настільки, як JPG.

Проблема виникає, коли потрібна хороша компресія, а також прозорість. Якщо ви не заперечуєте проти деградуючих зображень, ви можете використовувати програми квантування PNG, такі як pngquant , які ви можете перевірити в Інтернеті на TinyPNG . Майте на увазі, що деградація зображення, здійснена шляхом квантування самостійно, відрізняється від JPEG (що включає квантування, а також інші агресивні методи), тому не забудьте спробувати і те, і інше з великою різноманітністю налаштувань.

Якщо ви хочете агресивно зменшити розмір вашої дистрибуції, ви можете вручну обробити кожне зображення таким чином:

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

Порада: добре зберігати одні зображення в одному форматі, а інші - в іншому.

Існують і інші спеціалізовані формати, такі як DXT, ETC і PVRTC. Вони підтримують стиснення і можуть також завантажуватися стиснутими в пам'ять, але вони підтримуються лише певними графічними процесорами, і більшість цих графічних процесорів підтримують лише один з них, тому, якщо ви не знаєте точних технічних характеристик вашого цільового обладнання (примітний випадок - iPhone / iPad, який підтримує текстури PVRTC), вам слід уникати цих форматів.

Програма пам'яті

Я включив його сюди, тому що це те, що загальновідоме «пам’ять». Однак якщо у вашій грі використовується прискорення графіки (і якщо ви робите гру після 1998 року, ви, швидше за все, є), то єдине, що споживає пам'ять, - це ваші дескриптори текстури (всього кілька байт на зображення), які є лише впливає на кількість зображень, а не на їх розмір чи формат (у цьому є декілька застережень, але вони здебільшого не мають значення).

Якщо ваша платформа не має виділеної відеопам'яті, не прискорена апаратним забезпеченням або інші нечасті випадки, наступний розділ щодо VRAM відбудеться повністю або частково в оперативній пам’яті, але основні принципи будуть однаковими.

Відеопам'ять

Тут зберігатимуться ваші зображення після запуску програми. Взагалі формат, у якому ви їх зберігали, не матиме жодного значення, оскільки всі зображення декомпресуються перед завантаженням їх у відеопам'ять.

Тепер VRAM, спожитий вашими зображеннями, буде приблизно width * height * bitdepth для кожного зображення, завантаженого у VRAM. Тут можна помітити кілька речей:

  1. Ширина і висота, в яких зберігаються ваші зображення у VRAM, не обов'язково повинні відповідати розмірам оригінального зображення. Деякі графічні процесори можуть обробляти лише текстури розмірами 2, тому ваше зображення розміром 320х240 може бути фактично збережено в просторі 512x256 у VRAM, при цьому невикористана пам'ять ефективно витрачається. Деколи вам навіть не дозволяється завантажувати текстури розмірами, які не мають потужності 2 (як у GLES 1.1).

    Отже, якщо ви хочете звести до мінімуму використання VRAM, ви можете розглянути можливість об'єднати свої зображення та розмістити їх з потужностями 2, що також матиме перевагу в меншій кількості змін стану візуалізації при візуалізації. Детальніше про це пізніше.

  2. Бітдепт дуже важливий. Зазвичай текстури завантажуються в VRAM в 32-розрядному ARGB або 32-бітному XRGB, але якщо ваше обладнання може підтримувати 16-бітову глибину, і ви не заперечуєте, щоб мати менший бітовий глибину, ви можете вдвічі менше, ніж VRAM, спожитий кожним зображенням , що може бути цікавим для розгляду.

  3. Але незалежно від того, що ви робите, найважливішим фактором при розгляді обсягу VRAM, яку використовує ваша гра, є кількість зображень, які ви маєте в VRAM в даний момент часу. Це число, яке ви, швидше за все, хочете зберегти якнайменше, якщо хочете добре грати. Завантаження та вивантаження текстур у VRAM є дорогим, тому ви не можете просто завантажувати кожне зображення, коли ви збираєтесь ним користуватися. Ви повинні знайти баланс між попередньою завантаженням зображень, які ви, швидше за все, використовуватимете, та розвантажте їх, коли впевнені, що більше не збираєтесь їх використовувати. Виконання цього права не є банальним, і ви повинні продумати власну стратегію для вашої гри.

Швидкість виконання

Хоча це і не "пам'ять", вона дуже пов'язана з продуктивністю в іграх. Малювання зображень коштує дорого, і ви хочете переконатися, що ваше відображення проходить якомога швидше. Звичайно, тут формат не має значення, але інші речі:

  1. Розмір зображення (насправді це буде "розмір вибірки"): чим більша область зображення, яке ви збираєтеся малювати, тим більше часу знадобиться для його малювання. Відображення величезного зображення на невеликому ділянці екрану не дуже ефективно, тому існує методика під назвою mipmapping , яка складається з торгівлі VRAM для швидкості візуалізації, шляхом зберігання зображень кілька разів у кількох роздільних здатностях та використання найменшого, що може дати Вам потрібна якість у будь-який момент часу. Mipmapping можна виконувати, коли зображення завантажуються, що впливатиме на швидкість завантаження та використання VRAM, або при попередній обробці (шляхом збереження вручну різних версій одного і того ж зображення або за допомогою формату, який підтримує мип-карта, наприклад DDS), що вплине на зберігання та використання VRAM, але мало впливатиме на швидкість завантаження.

  2. Відображення змін стану. Ви, швидше за все, захочете намалювати кілька різних зображень на екрані одночасно. Однак GPU може використовувати лише одне вихідне зображення у будь-який момент часу (це неправда, але будь ласка, майте тут мене зі мною). В даний час використовується зображення для візуалізації є одним з багатьох станів візуалізації , і це дорого. Отже, якщо ви збираєтесь використовувати одне і те ж зображення кілька разів (пам’ятаєте, коли я згадав атласи текстури ?), Ви помітите величезний приріст продуктивності, якщо ви повторно використовуєте зображення, перш ніж змінити стан візуалізації та почати використовувати інше зображення (крім цього є інші стани візуалізації, і точна настройка порядку, в якому ви малюєте свої речі, щоб мінімізувати зміни стану візуалізації, є дуже поширеною діяльністю при підвищенні продуктивності гри)

Однак оптимізація використання зображень є дуже складною темою, і те, що я написав тут, - це дуже широкий і спрощений огляд деяких факторів, які вам доведеться враховувати при написанні гри, тому я думаю, що це, безумовно, найкраще, якщо ви будете простою, і оптимізувати лише тоді, коли вам це потрібно. У більшості випадків передчасна оптимізація є непотрібною (а іноді навіть згубною), тому прийміть це легко.


25
+1. Це надзвичайно вичерпна відповідь, яка охоплює дуже багато ґрунту. Я не впевнений, що розмір дескрипторів текстури вимагав стільки ж місця, скільки у нього, і згадка DXT / ETC / PVRTC повинна дійсно включати, що кожен з цих працює лише на деяких платформах - вони не є міжплатформенними стандарти, які можна використовувати скрізь, як JPEG, PNG та GIF. Але загалом дуже вражений. Це набагато більше, ніж просто "незначне зауваження", що відповідає моїй відповіді! : D
Тревор Пауелл

9
@PandaPajama: Можливо, ні, але це напрочуд краща відповідь, ніж це питання заслуговує.
Маркс Томас

1
+1 та більше, якщо я міг би. Це приголомшлива відповідь і має бути стандартним орієнтиром для будь-якого питання про "ефективність пам'яті", оскільки це настільки ефективно розвінчає загальний міф, що використання менше пам'яті - це завжди найкращий підхід, а не лише для зображень. Один пункт, який я б запропонував додати, - це те, що в разі неприскореного випадку, якщо потрібна якась декомпресія на ходу під час її малювання, це може становити неприйнятну ефективність роботи.
Максим Мінімус

2
Я хотів би запропонувати PNGGauntlet . Це може зробити величезну оптимізацію без збитків для розмірів файлів PNG, яка може доповнити, особливо якщо у вас багато спрайтів. На жаль, це лише Windows, але альтернативи вказані на домашній сторінці для інших ОС.
orlp

1
@DavidDimalanta У мене немає досвіду роботи з libgdx, але, як я можу побачити з документації setEnforcePotImages, він забороняє примусово використовувати 2 текстури розміру для OpenGLES 1.0. Це не гарна ідея, оскільки не все обладнання підтримує текстури без потужності-2. OpenGLES 2.0 вимагає підтримки текстур без потужності-2, тому якщо ви орієнтуєтесь на 2.0, ви можете використовувати текстури будь-якого розміру. Для отримання додаткової інформації зверніться до документації libgdx.
Піжама Panda

26

Після завантаження зображення з диска та форматування для візуалізації воно використовуватиме однаковий об'єм пам'яті незалежно від того, збережено це зображення на диску за допомогою PNG, JPEG або GIF.

Загальне правило: JPEG - це формат втрати, який погіршить якість зображення, щоб зменшити зображення на диску. PNG, з іншого боку, є форматом зображення без втрат, і, як правило, призводить до збільшення розміру файлів на диску. GIF також технічно є форматом без втрат, але підтримує лише максимум 256 кольорів на зображення, тому висококольорове зображення часто спричиняє великі втрати якості, якщо збережене як GIF.

Але це лише для їх дискового представлення. У пам'яті вони обидва будуть розширюватися в один і той же формат текстури, використовуючи однаковий об'єм пам'яті, незалежно від того, зберегли ви їх на диску як PNG, або як JPEG, або як GIF.


Тож не розмір файлу змінюється за розміром пам'яті, а за розміром файлу?
Tredecies Nocturne

Ні. Розмір в пам'яті базується на розмірах зображення та розмірі зображення. Будь-яке стиснення файлу зображення знімається, коли зображення завантажується в пам’ять, яке виводиться на екран. (Оскільки GPU не може відображати PNG, JPEG або ін.) Зображення розгортаються у загальні піксельні карти, щоб GPU міг з ними працювати.)
Тревор Пауелл,

2
Це не на 100% правда. Більшість сучасних графічних процесорів (включаючи вбудовані) підтримують завантаження та зберігання стислих текстур у графічній пам'яті, такі формати, як DXT, ETC та PVRTC, є найпоширенішими у вбудованому світі. Звичайно, вам доведеться зберігати текстури в цих форматах в першу чергу замість PNG / JPG / GIF.
Піжама Panda

6
Питання було явним вибором між PNG / JPG / GIF, жоден з яких не підтримується в будь-якому графічному процесорі, про який я знаю. У оригінального запитувача виникло достатньо проблем з розрізненням розміру файлу на диску та місця, зайнятого в оперативній пам'яті, що я вважав, що додавання більше форматів файлів лише заплутає фундаментальну проблему. Хоча не соромтеся дати власну відповідь.
Тревор Пауелл

2
Мій коментар - це лише примітка. Якби я надавав відповідь, я, швидше за все, написав би те саме, що і ви, плюс мій коментар як остаточне заключне слово. Мені нічого більше додати, тому я уникаю повторень, надаючи власну відповідь.
Піжама Panda

3

Це залежить.

Jpeg є найбільш ефективним для фотографій. Це не без втрат, але артефакти, введені стисненням, найменш помітні в цьому випадку використання.

PNG без втрат і найефективніший для піксельного мистецтва з різкими лініями та кількома кольорами. Він також підтримує альфа-прозорість.

GIF не може зробити нічого, що PNG не може зробити краще, за винятком його здатності зберігати анімацію. Але це актуально лише в контексті веб-додатків. У розробці ігор ви, як правило, створюєте анімацію за допомогою spritesheet.

Зауважте, що при використанні графічного движка типу Libgdx він, швидше за все, розпакує зображення відразу після завантаження, а потім збереже їх у пам'яті як нестиснені значення RGBA. Таким чином, формат зображення має значення лише для швидкості завантаження і мав простір приводу (або використання пропускної здатності, коли ви надсилаєте їх по мережі).


2

Я не знаю багато про libgdx, але про формати зображень та графіку:

JPEG дуже хороший для реальних фотографій. Вони втрачають, але на фотографіях ви не побачите артефактів, якщо не сфотографуєте гострі краї з простими кольоровими пробілами, як, наприклад, написаний текст чи комікси. Використовуйте їх для великої фонової графіки.

GIF застарілий, він може зберігати лише палітри кольорів (до 8 біт на піксель) одним виділеним кольором для повної прозорості. Це дозволяє невеликі анімації на основі кадрів. Колись був патент на його алгоритм упаковки, щоб його не можна було скрізь використовувати легально. Через цей патент був розроблений PNG.

PNG - це більш-менш блискавкова растрова карта, яка може зберігати RGB + альфа (до 32 біт) та інші формати пікселів. Він спеціалізований для розпакування швидкості невеликих частин цієї картинки, що зручно для дуже маленьких і повільних пристроїв (як 10-річний мобільний телефон), але сьогодні бібліотеки просто розпаковують їх до растрових зображень при завантаженні.

PNG кращий за GIF за розміром, швидкістю та можливостями, але якщо ви хочете ефективно зберігати растрові карти, я б радив: .PNM.BZ2 ([редагувати] Через різні способи упаковки .PNM.BZ2 не завжди є більш ефективним ніж .PNG. [/ редагувати])

PNM / PBM / PGM / PAM є простими форматами растрових зображень із заголовками KISS у простому тексті. Використання gzip для цих файлів призведе до розміру файлу, подібного до PNG, тому bzip2 є кращим рішенням для цього. Якщо ви збираєтеся використовувати растрові карти внутрішньо у своїй програмі, можливо, ви захочете використовувати компресовані bzip2 растрові карти в контейнері .tar або .zip. Якщо у вас немає bzip2, використання PNM в контейнері-блискавці (блискавка з максимальним стисненням) може бути подібним до використання PNG-файлів. - Отже, зберігання PNG-файлів у ZIP-файлі може мати лише невелику користь або не матиме користі - це, швидше за все, просто збільшить час для завантаження зображення.

Крім того, це хороший вибір для зберігання декількох маленьких спрайт / зображень в одній растровій карті, особливо коли вони вам потрібні в одній і тій же ситуації разом.


Чи доступний чи доступний файл PNM для всіх ОС ОС та настільних комп'ютерів?
Девід Дімаланта

1
@David Dimalanta: Я не знаю, де це підтримується, а де - ні. Якщо ви хочете програмувати з PNM, то ви рідко хочете використовувати будь-яку бібліотеку, оскільки цей формат занадто простий, щоб вибрати будь-який API. Через це він читається та записується з усіма існуючими мовами програмування, які підтримують читання / запис бінарних файлів. Звичайно, ви можете використовувати Netpbm на будь-якій ОС, не тільки Unix. З іншого боку, я не знаю, які загальні бібліотеки зображень це не підтримують. Це не стислий формат, тому його рідко використовують для зберігання зображень на диску. дивіться en.wikipedia.org/wiki/Netpbm_format
comonad

1

Оскільки формат зберігання JPEG, мабуть, найкращий вибір для деяких текстур, таких як трава чи стіни, де втрата інформації, ймовірно, не виявляється. Слідом за PNG, коли вам потрібна прозорість або коли ви не можете заплатити за втрату інформації, наприклад, спрайтів у двовимірній грі (програвач, вороги, скарбниця), ви, ймовірно, хочете використовувати PNG для цих зображень.

Якщо говорити про вартість пам'яті, формат, який використовується для зберігання ігрової графіки у файловій системі, взагалі не доречний. Якщо ви зберігаєте піксельні буфери у VRAM або RAM (програмний рендер), ви, ймовірно, зберігаєте їх нестисненими, оскільки ігри сприяють швидкому зчитуванню пікселів та пам'яті, що використовується кожним піксельним буфером.

У стислих даних, що зберігаються в пам'яті, немає сенсу, окрім того, що ви зберігаєте якийсь кеш-пам'ять, щоб зберегти зчитування з диска, але вам, ймовірно, доведеться читати з цього кеша в нестисненому стані для зображень, які використовувались у певний час у вашій грі.

Дані стислих зображень мають трохи більше сенсу, якщо можливо швидке апаратне декодування. Принаймні для нормального відображення я пам'ятаю це http://en.wikipedia.org/wiki/3Dc . За допомогою цього можна зберегти деякі VRAM. Я ще не знаю інших прикладів апаратного декодування.

У резюме: незалежно від форматів, які використовувались у вашій грі для зберігання графіки в постійному сховищі, вам доведеться розшифрувати її та підтримувати нестиснену версію в динамічній пам'яті, відеопам'яті або обох, щоб мати можливість швидко виводити їх за потреби.

Нарешті: я настільний хлопець. Коли я кажу "пам'ять", я завжди маю на увазі динамічну пам'ять. Коли я кажу "диск", "файлова система" або "постійне зберігання", я завжди маю на увазі те, що ваш пристрій використовує як постійне сховище, як правило, я думаю про жорсткі диски. Коли ви сказали "ефективність пам'яті", я взяв це за "динамічну пам'ять", а не за "стійке зберігання". Останнім часом я бачу дуже багато людей, які використовують слово "пам'ять" для позначення "постійного зберігання" (можливо, це термінологія мобільних пристроїв?).


Чи можливо також, що на пам'ять не впливає не JPEG, ані PNG, а розмір файлу?
Tredecies Nocturne

Так. Ви виберете будь-який із обговорюваних форматів, розмірковуючи при збереженні дискового простору або пропускної здатності. Коли ви завантажуєте зображення в гру, будь-яка бібліотека / движок, який я знаю, розшифрує їх на нестиснені піксельні буфери (мислити в буферах пікселів як масив значень RGB або RGBA, де кожен канал зазвичай займає 1 байт в оперативній пам’яті / VRAM, якщо використовується 32 біта на кожен пікселів, це, мабуть, все, що роблять).
Hatoru Hansou
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.