Какой формат изображения более эффективен для экономии памяти? PNG, JPEG или GIF?
Какой формат изображения более эффективен для экономии памяти? PNG, JPEG или GIF?
Ответы:
Термины «память» и «эффективность» обычно используются неправильно, поэтому я дам вам ответ по четырем различным элементам, которые могут повлиять на производительность вашей игры.
Я буду слишком упрощать слишком много вещей, чтобы быть кратким и кратким, но в этом тексте ниже есть тонны неточностей, так что возьмите это с щепоткой соли. Однако основные понятия должны быть понятны.
Место хранения
Это размер, который ваши изображения потребляют при распространении программного обеспечения. Чем больше места занимают ваши ресурсы, тем дольше будет загрузка (как с вашего сайта). Если вы распространяете на физических носителях, таких как компакт-диски или 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. Здесь есть пара вещей, на которые стоит обратить внимание:
Ширина и высота, в которой ваши изображения хранятся в VRAM, не обязательно будут соответствовать вашим исходным изображениям. Некоторые графические процессоры могут обрабатывать только текстуры с размерами в степени 2, поэтому изображение 320x240 может фактически храниться в пространстве 512x256 в VRAM, при этом неиспользуемая память эффективно теряется. Иногда вам даже не разрешается загружать текстуры с размерами, не равными степени 2 (как в GLES 1.1).
Поэтому, если вы хотите минимизировать использование VRAM, вы можете подумать о том, чтобы увеличить ваши изображения и установить для них размеры степеней 2, что также будет иметь преимущество в меньшем количестве изменений состояния рендеринга при рендеринге. Подробнее об этом позже.
Глубина очень важна. Обычно текстуры загружаются в VRAM в 32-битном ARGB или 32-битном XRGB, но если ваше оборудование поддерживает 16-битную глубину, и вы не возражаете против более низкой разрядности, вы можете вдвое уменьшить количество VRAM, потребляемое каждым изображением. , что может быть чем-то интересным для рассмотрения.
Но независимо от того, что вы делаете, самым важным фактором при рассмотрении количества VRAM, которое ваша игра использует, является количество изображений, которые вы имеете в VRAM в данный момент времени. Это число, которое вы, скорее всего, хотите сохранить как можно ниже, если хотите получить хорошую игру. Загрузка и выгрузка текстур в VRAM стоит дорого, поэтому вы не можете просто загружать каждое изображение, когда собираетесь его использовать. Вы должны найти баланс между предварительной загрузкой изображений, которые вы, скорее всего, будете использовать, и выгрузить их, если вы уверены, что больше не будете их использовать. Делать это правильно не тривиально, и вы должны думать о своей собственной стратегии для вашей конкретной игры.
Скорость исполнения
Хотя это и не «память», это очень связано с производительностью в играх. Рисование изображений стоит дорого, и вы хотите, чтобы ваш рендеринг работал как можно быстрее. Конечно, здесь формат не имеет значения, но есть и другие вещи:
Размер изображения (на самом деле это будет «размер выборки»): чем больше область изображения, которое вы собираетесь нарисовать, тем больше времени потребуется для ее рисования. Рендеринг огромного изображения в небольшом участке экрана не очень эффективен, поэтому есть метод, называемый mipmapping , который состоит из торговли VRAM за скорость рендеринга, сохраняя ваши изображения несколько раз в нескольких разрешениях и используя наименьшее, которое может дать Вы нужного качества в любой момент времени. Mipmapping может выполняться при загрузке изображений, что повлияет на скорость загрузки и использование VRAM, или при предварительной обработке (путем ручного сохранения разных версий одного и того же изображения или использования формата, который изначально поддерживает mipmapping, такого как DDS), что повлияет на хранилище и использование VRAM, но это мало повлияет на скорость загрузки.
Визуализация изменений состояния. Скорее всего, вы захотите нарисовать несколько разных изображений на экране одновременно. Тем не менее, графический процессор может использовать только один исходный образ в любой момент времени (это не так, но, пожалуйста, потерпите меня здесь). Используемое в настоящее время изображение для рендеринга является одним из многих состояний рендеринга , и это дорого. Поэтому, если вы собираетесь использовать одно и то же изображение несколько раз (помните, когда я упомянул атласы текстур ?), Вы заметите огромный выигрыш в производительности, если вы будете использовать изображение как можно чаще, прежде чем изменить состояние рендера и начать использовать другое изображение (кроме этого есть другие состояния рендеринга, и точная настройка порядка, в котором вы рисуете свои вещи, чтобы минимизировать изменения состояния рендеринга, является очень распространенным действием при повышении производительности игры)
Тем не менее , оптимизация использования изображений является очень сложной темой, и то, что я написал здесь, является очень широким и упрощенным обзором некоторых факторов, которые вы должны учитывать при написании игры, поэтому я думаю, что определенно будет лучше, если вы сделаете это простым, и оптимизировать только тогда, когда вам действительно нужно это сделать. В большинстве случаев преждевременная оптимизация не нужна (а иногда даже вредна), так что успокойтесь.
setEnforcePotImages
, он отключает применение мощности текстур 2-го размера для OpenGLES 1.0. Это не очень хорошая идея, так как не все аппаратные средства поддерживают текстуры не-степени-2. OpenGLES 2.0 требует поддержки текстур, не относящихся к степени 2, поэтому, если вы нацеливаетесь на 2.0, вы можете использовать текстуры любого размера. Для получения дополнительной информации обратитесь к документации по libgdx.
После того как изображение загружено с диска и отформатировано для рендеринга, оно будет использовать одинаковый объем памяти независимо от того, было ли это изображение сохранено на диск с использованием PNG, JPEG или GIF.
Общее правило: JPEG - это формат с потерями, который ухудшает качество изображения, чтобы уменьшить его на диске. PNG, с другой стороны, является форматом изображения без потерь, и поэтому обычно приводит к увеличению размера файла на диске. GIF также технически является форматом без потерь, но поддерживает только максимум 256 цветов на изображение, поэтому при сохранении в формате GIF изображение с высоким качеством часто будет иметь значительные потери качества.
Это только для их представления на диске, хотя. В памяти они оба будут расширяться в один и тот же формат текстур, используя один и тот же объем памяти, независимо от того, сохраняли ли вы их на диск в формате PNG, JPEG или GIF.
По-разному.
JPEG наиболее эффективен для фотографий. Это не без потерь, но артефакты, представленные сжатием, наименее заметны в этом сценарии использования.
PNG без потерь и наиболее эффективен для пиксельной графики с четкими линиями и небольшим количеством цветов. Он также поддерживает альфа-прозрачность.
GIF не может делать ничего, что PNG не может делать лучше, за исключением его способности хранить анимацию. Но это актуально только в контексте веб-приложений. В разработке игр вы обычно создаете анимацию с помощью таблицы спрайтов.
Обратите внимание, что при использовании графического движка, такого как Libgdx, он, скорее всего, распаковывает изображения сразу после загрузки, а затем сохраняет их в памяти как несжатые значения RGBA. Таким образом, формат изображения имеет значение только для скорости загрузки и наличия дискового пространства (или использования полосы пропускания при отправке их по сети).
Я не знаю много о libgdx, но о форматах изображений и графике:
JPEG очень хорош в случае реальных фотографий. Они с потерями, но вы не увидите артефакты на фотографиях, если не сделаете снимки с острыми краями с простыми цветными промежутками, такими как, например, письменный текст или комиксы. Используйте их для большой фоновой графики.
GIF устарел, он может хранить только палитровые цвета (до 8 бит на пиксель) с одним выделенным цветом для полной прозрачности. Это позволяет небольшие анимации на основе кадров. Когда-то был патент на его алгоритм упаковки, так что он не мог быть использован везде легально. Из-за этого патента была разработана PNG.
PNG - это более или менее сжатое растровое изображение, которое может хранить RGB + альфа (до 32 бит) и другие пиксельные форматы. Он предназначен для быстрого распаковывания небольших частей этого изображения, что удобно для очень маленьких и медленных устройств (например, 10-летний мобильный телефон), но современные библиотеки просто распаковывают их в растровые изображения при загрузке.
PNG лучше, чем GIF по размеру, скорости и возможностям, но если вы хотите эффективно хранить растровые изображения, я бы посоветовал: .PNM.BZ2 ([править] Из-за другого метода упаковки .PNM.BZ2 не всегда более эффективен чем .PNG. [/ edit])
PNM / PBM / PGM / PAM - это простые растровые форматы с KISS-заголовками в виде простого текста. Использование gzip приведет к тому, что размер файла будет похож на PNG, поэтому bzip2 - лучшее решение для этого. Если вы собираетесь использовать растровые изображения внутри вашей программы, вы можете использовать сжатые растровые изображения bzip2 в контейнере .tar или .zip. Если у вас нет bzip2, использование PNM в zip-контейнере (zip с максимальным сжатием) может быть аналогично использованию PNG. - Таким образом, хранение PNG в ZIP-файле может принести лишь небольшую выгоду или не принесет никакой пользы - скорее всего, это просто увеличит время загрузки изображения.
Кроме того, это хороший выбор для хранения нескольких маленьких спрайтов / изображений в одном растровом изображении, особенно когда они нужны вам в одной и той же ситуации вместе.
В качестве формата хранения JPEG, вероятно, является лучшим выбором для некоторых текстур, таких как трава или стены, где потеря информации, вероятно, не обнаруживается. Вслед за PNG, когда вам нужна прозрачность или когда вы не можете расплатиться с потерей информации, например спрайтов в 2D-игре (игрок, враги, сундук с сокровищами), вы, вероятно, захотите использовать PNG для этих изображений.
Говоря о стоимости памяти, формат, используемый для хранения игровой графики в файловой системе, вообще не имеет значения. Либо, если вы храните пиксельные буферы в VRAM или RAM (программный рендерер), вы, вероятно, храните их в несжатом виде, поскольку игры предпочитают быстрое считывание пикселей по сравнению с памятью, используемой каждым пиксельным буфером.
Сжатые данные, хранящиеся в памяти, не имеют смысла, за исключением того, что вы сохраняете какой-то кеш для сохранения чтения с диска, но вам, вероятно, придется читать из этого кеша в несжатое состояние для изображений, используемых в данный момент в вашей игре.
Сжатые данные изображения имеют немного больше смысла, если бы было возможно быстрое аппаратное декодирование. По крайней мере, для нормального отображения я помню этот http://en.wikipedia.org/wiki/3Dc . С этим вы можете сохранить некоторые VRAM. Я пока не знаю других примеров аппаратного декодирования.
В заключение: независимо от того, какие форматы используются в вашей игре для хранения графики в постоянном хранилище, вам придется декодировать ее и поддерживать несжатую версию в динамической памяти, видеопамяти или в обоих этих файлах, чтобы можно было быстро их визуализировать при необходимости.
И наконец: я парень на рабочем столе. Когда я говорю «память», я всегда имею в виду динамическую память. Когда я говорю «диск», «файловая система» или «постоянное хранилище», я всегда имею в виду то, что ваше устройство использует как постоянное хранилище, обычно я думаю о жестких дисках. Когда вы сказали «эффективность памяти», я принял это за «динамическую память», а не «постоянное хранилище». В последнее время я вижу много людей, использующих слово «память» для обозначения «постоянного хранения» (может быть, это терминология мобильных устройств?).