¿Qué formato de imagen es más eficiente para ahorrar memoria? PNG, JPEG o GIF?
graphics
graphics-programming
image
memory-efficiency
Tredecies Nocturne
fuente
fuente
Respuestas:
"Memoria" y "eficiencia" son términos comúnmente mal utilizados, así que te daré una respuesta para cuatro elementos diferentes que pueden afectar el rendimiento de tu juego.
Voy a simplificar demasiado demasiadas cosas para que sea breve y conciso, pero hay toneladas de imprecisiones en este texto a continuación, así que tómalo con una pizca de sal. Sin embargo, los conceptos principales deben ser entendibles.
Almacenamiento
Este es el tamaño que consumen sus imágenes en su distribución de software. Cuanto más espacio consuman sus recursos, mayor será la descarga (como desde su sitio web). Si está distribuyendo en medios físicos, como CD o DVD, probablemente tendrá que hacer algunas optimizaciones serias en este frente.
En general, JPEG comprime lo mejor para fotografías e imágenes sin bordes nítidos. Sin embargo, sus imágenes tendrán una calidad degradada porque JPEG usa compresión con pérdida (puede ajustar el nivel de compresión / degradación al exportar imágenes como JPEG. Consulte la documentación de su software de imágenes para obtener más información al respecto).
Sin embargo, por muy bueno que sea JPEG, no admite transparencia . Esto es crucial si desea tener imágenes que se muestren a través de otros, o si desea imágenes con formas irregulares. GIF es una buena opción, pero ha sido reemplazado en gran medida por PNG (solo hay unas pocas cosas que GIF admite que PNG no admite, pero son en gran medida irrelevantes en la programación de juegos).
PNG admite transparencia (y semitransparencia), comprime datos sin degradar la calidad (es decir, utiliza una compresión sin pérdidas) y comprime bastante bien, pero no tanto como JPG.
El problema surge cuando necesita una buena compresión, así como también transparencia. Si no le importan las imágenes ligeramente degradadas, puede usar programas de cuantificación PNG como pngquant , que puede probar en línea en TinyPNG . Tenga en cuenta que la degradación de la imagen realizada por la cuantización por sí sola es diferente a la de JPEG (que incluye la cuantificación y otras técnicas agresivas), así que asegúrese de probar ambas, con una amplia variedad de configuraciones.
Si desea minimizar agresivamente el tamaño de su distribución, puede procesar manualmente cada imagen de esta manera:
Consejo: está bien almacenar algunas imágenes en un formato y otras en otro formato.
Existen otros formatos especializados como DXT, ETC y PVRTC. Admiten compresión y también pueden cargarse comprimidos en la memoria, pero solo son compatibles con GPU específicas, y la mayoría de estas GPU solo admiten una de ellas, por lo que a menos que conozca las especificaciones exactas de hardware de su hardware de destino (un caso notable es iPhone / iPad, que admite texturas PVRTC), debe evitar estos formatos.
Memoria de programa
Lo incluí aquí, porque esto es lo que comúnmente se conoce como "memoria". Sin embargo, si su juego usa aceleración de gráficos (y si está haciendo un juego después de 1998, lo más probable es que lo haga), entonces lo único que consumirá memoria son sus descriptores de textura (solo unos pocos bytes por imagen), que es solo efectuado por la cantidad de imágenes, y no por su tamaño o formato (esto tiene algunas advertencias, pero en su mayoría son irrelevantes).
Si su plataforma no tiene memoria de video dedicada, no está acelerada por hardware u otros casos poco comunes, entonces la siguiente sección sobre VRAM sucederá total o parcialmente en la RAM, pero los principios principales serán los mismos.
Memoria de video
Aquí es donde sus imágenes se almacenarán una vez que su programa se esté ejecutando. En general, el formato en el que los almacenó no hará ninguna diferencia aquí, ya que todas las imágenes se descomprimen antes de cargarlas en la memoria de video.
Ahora, la VRAM consumida por sus imágenes será aproximadamente
width * height * bitdepth
para cada imagen cargada en VRAM. Hay un par de cosas para notar aquí:El ancho y el alto en el que se almacenan sus imágenes en VRAM no coincidirán necesariamente con los de su imagen original. Algunas GPU solo pueden manejar texturas con tamaños en potencias de 2, por lo que su imagen de 320x240 en realidad puede almacenarse en un espacio de 512x256 en VRAM, con la memoria no utilizada efectivamente desperdiciada. Algunas veces ni siquiera se le permite cargar texturas con tamaños que no son potencias de 2 (como en GLES 1.1).
Entonces, si desea minimizar el uso de VRAM, es posible que desee considerar reducir sus imágenes y dimensionarlas con potencias de 2, lo que también tendrá la ventaja de menos cambios de estado de renderizado al renderizar. Más sobre esto más tarde.
La profundidad de bits es muy importante. Por lo general, las texturas se cargan en VRAM en ARGB de 32 bits o XRGB de 32 bits, pero si su hardware puede admitir profundidades de 16 bits, y no le importa tener una profundidad de bits menor, puede reducir la mitad de la cantidad de VRAM consumida por cada imagen , que puede ser algo interesante a considerar.
Pero no importa lo que hagas, el factor más importante al considerar la cantidad de VRAM que usa tu juego es la cantidad de imágenes que tienes en VRAM en un momento dado. Este es el número que probablemente quieras mantener lo más bajo posible si quieres un buen juego. Cargar y descargar texturas en VRAM es costoso, por lo que no puede cargar cada imagen cada vez que la va a usar. Debe encontrar un equilibrio entre precargar las imágenes que probablemente usará y descargarlas cuando esté seguro de que ya no las va a usar. Hacer esto correctamente no es trivial, y debes pensar en tu propia estrategia para tu juego en particular.
Velocidad de ejecución
Aunque no es "memoria", está muy relacionado con el rendimiento en los juegos. Dibujar imágenes es costoso, y desea asegurarse de que su renderizado se ejecute lo más rápido posible. Por supuesto, aquí, el formato no importa, pero otras cosas sí:
Tamaño de imagen (en realidad, sería "tamaño de muestreo"): cuanto más grande sea la región de una imagen que va a dibujar, más tiempo llevará dibujarla. Renderizar una imagen enorme en una pequeña sección de la pantalla no es muy eficaz, por lo que existe una técnica llamada mipmapping , que consiste en intercambiar VRAM por la velocidad de renderizado, almacenando sus imágenes varias veces a varias resoluciones y utilizando la más pequeña que pueda proporcionar Usted la calidad requerida en cualquier momento. Mipmapping se puede realizar cuando se cargan las imágenes, lo que afectará la velocidad de carga y el uso de VRAM, o en el preprocesamiento (almacenando manualmente diferentes versiones de la misma imagen o utilizando un formato que admita de forma nativa mipmapping como DDS), lo que afectará el almacenamiento y el uso de VRAM, pero tendrá poco impacto en la velocidad de carga.
Renderizar cambios de estado. Lo más probable es que desee dibujar varias imágenes diferentes en la pantalla al mismo tiempo. Sin embargo, la GPU solo puede usar una única imagen de origen en un momento dado (esto no es cierto, pero tenga paciencia conmigo aquí). La imagen utilizada actualmente para la representación es uno de los muchos estados de representación , y es costosa. Entonces, si va a usar la misma imagen varias veces (¿recuerda cuando mencioné los atlas de textura ?), Notará una gran ganancia de rendimiento si reutiliza una imagen tanto como pueda antes de cambiar el estado de renderizado y comenzar a usar un imagen diferente (hay otros estados de render aparte de esto, y ajustar el orden en el que dibuja sus cosas para minimizar los cambios de estado de render es una actividad muy común cuando se mejora el rendimiento de un juego)
Sin embargo , la optimización del uso de imágenes es un tema muy complejo, y lo que escribí aquí es una visión general muy amplia y simplificada de algunos de los factores que tendrá que tener en cuenta al escribir un juego, por lo que creo que definitivamente es mejor si lo mantiene simple, y solo optimiza cuando realmente necesites hacerlo. La mayoría de las veces, la optimización prematura es innecesaria (y a veces incluso perjudicial), así que tómalo con calma.
fuente
setEnforcePotImages
, deshabilita la aplicación de potencia de texturas de 2 tamaños para OpenGLES 1.0. Esta no es una buena idea, ya que no todo el hardware admite texturas sin potencia de 2. OpenGLES 2.0 requiere soporte para texturas sin potencia de 2, por lo que si está apuntando a 2.0, puede usar texturas de cualquier tamaño. Para obtener más información, consulte la documentación de libgdx.Una vez que se carga una imagen del disco y se formatea para renderizarla, usará la misma cantidad de memoria independientemente de si esa imagen se guardó en el disco usando PNG, JPEG o GIF.
Regla general: JPEG es un formato con pérdida y degradará la calidad de la imagen para hacerla más pequeña en el disco. PNG, por otro lado, es un formato de imagen sin pérdidas, por lo que normalmente dará como resultado tamaños de archivo más grandes en el disco. GIF también es técnicamente un formato sin pérdidas, pero solo admite un máximo de 256 colores por imagen, por lo que una imagen de alto color a menudo incurrirá en una gran pérdida de calidad si se guarda como un GIF.
Sin embargo, eso es solo por su representación en el disco. En la memoria, ambos se expandirán en el mismo formato de textura, utilizando la misma cantidad de memoria, independientemente de si los guardó en el disco como PNG, JPEG o GIF.
fuente
Depende.
Jpeg es más eficiente para fotografías. No es sin pérdida, pero los artefactos introducidos por la compresión son menos visibles en este caso de uso.
PNG es sin pérdidas y más eficiente para pixel art con líneas definidas y pocos colores. También es compatible con alfa-transparencia.
GIF no puede hacer nada PNG no puede hacerlo mejor, excepto por su capacidad de almacenar animaciones. Pero esto solo es relevante en el contexto de las aplicaciones web. En el desarrollo de juegos, generalmente creas animaciones usando una hoja de sprites.
Tenga en cuenta que cuando utiliza un motor gráfico como Libgdx, lo más probable es que descomprima las imágenes justo después de cargarlas y luego las guardará en la memoria como valores RGBA sin comprimir. Por lo tanto, el formato de imagen solo es importante para la velocidad de carga y tenía espacio en el disco (o uso de ancho de banda cuando los envía por la red).
fuente
No sé mucho sobre libgdx, pero sobre formatos de imagen y gráficos:
JPEG es muy bueno en casos de fotos del mundo real. Son con pérdida, pero no verá artefactos en las fotos a menos que tome imágenes de bordes afilados con espacios de color liso, como por ejemplo texto escrito o cómics. Úselos para grandes gráficos de fondo.
GIF es obsoleto, solo puede almacenar colores paletizados (hasta 8 bits por píxel) con un color dedicado para una transparencia completa. Permite pequeñas animaciones basadas en cuadros. Una vez hubo una patente en su algoritmo de empaque para que no pudiera usarse legalmente en todos lados Debido a esa patente, se desarrolló PNG.
PNG es más o menos un mapa de bits comprimido que puede almacenar RGB + alfa (hasta 32 bits) y otros formatos de píxeles. Está especializado para descomprimir rápidamente partes pequeñas de esa imagen, lo cual es conveniente para dispositivos muy pequeños y lentos (como un teléfono celular de 10 años), pero las bibliotecas de hoy simplemente los descomprimen en mapas de bits cuando están cargados.
PNG es mejor que GIF en tamaño, velocidad y características, pero si desea almacenar mapas de bits de manera eficiente, le sugiero: .PNM.BZ2 ([editar] Debido al diferente método de empaque, .PNM.BZ2 no siempre es más eficiente que .PNG. [/ edit])
PNM / PBM / PGM / PAM son formatos de mapa de bits sin formato con encabezados KISS en texto sin formato. El uso de gzip en esos dará como resultado un tamaño de archivo similar a PNG, por lo que bzip2 es la mejor solución para eso. Si va a utilizar mapas de bits internamente en su programa, es posible que desee utilizar mapas de bits comprimidos bzip2 en un contenedor .tar o .zip. Si no tiene bzip2, usar PNM en un contenedor zip (zip con compresión máxima) podría ser similar a usar PNG. - Por lo tanto, almacenar PNG en un archivo ZIP puede tener un beneficio pequeño o nulo, lo más probable es que aumente el tiempo de carga de la imagen.
Además de eso, es una buena opción almacenar varios sprites / imágenes pequeños en un mapa de bits, especialmente cuando los necesita todos juntos en la misma situación.
fuente
Como el formato de almacenamiento JPEG es probablemente la mejor opción para algunas texturas como césped o paredes, donde la pérdida de información es probablemente indetectable. Seguido por PNG cuando necesita transparencia o cuando no puede pagar con la pérdida de información, por ejemplo, sprites en un juego 2D (el jugador, los enemigos, un cofre del tesoro), probablemente quiera usar PNG para esas imágenes.
Cuando se habla del costo de la memoria, el formato utilizado para almacenar gráficos de juegos en el sistema de archivos no es relevante en absoluto. Si almacena almacenamientos intermedios de píxeles en VRAM o RAM (procesador de software), probablemente los tenga almacenados sin comprimir, porque los juegos favorecen la lectura rápida de píxeles frente a la memoria utilizada por cada almacenamiento intermedio de píxeles.
Tener datos comprimidos almacenados en la memoria no tiene sentido, excepto que mantiene algún tipo de caché para guardar las lecturas del disco, pero probablemente tenga que leer desde ese caché a un estado sin comprimir para las imágenes en uso en un momento dado de su juego.
Los datos de imagen comprimidos tienen un poco más de sentido si fuera posible una rápida decodificación de hardware. Al menos para el mapeo normal, recuerdo esto http://en.wikipedia.org/wiki/3Dc . Con eso puedes guardar algo de VRAM. Todavía no conozco otros ejemplos de decodificación de hardware.
En resumen: cualquiera que sea el formato utilizado para que su juego almacene gráficos en un almacenamiento persistente, tendrá que decodificarlo y mantener una versión sin comprimir en la memoria dinámica, la memoria de video o ambas, para poder renderizarlas rápidamente cuando sea necesario.
Finalmente: soy un chico de escritorio. Cuando digo "memoria" siempre me refiero a la memoria dinámica. Cuando digo "disco", "sistema de archivos" o "almacenamiento persistente", siempre me refiero a lo que sea que su dispositivo use como almacenamiento persistente, generalmente pienso en discos duros. Cuando dijiste "eficiencia de memoria", lo tomé por "memoria dinámica", no por "almacenamiento persistente". Últimamente, veo a muchas personas que usan la palabra "memoria" para referirse a "almacenamiento persistente" (¿tal vez esa es la terminología de los dispositivos móviles?).
fuente