¿Cómo es PNG sin pérdida dado que tiene un parámetro de compresión?

157

Se dice que los archivos PNG usan compresión sin pérdidas. Sin embargo, cada vez que estoy en un editor de imágenes, como GIMP e intento guardar una imagen como un archivo PNG, me pide el parámetro de compresión, que oscila entre 0 y 9. Si tiene un parámetro de compresión que afecta la precisión visual de la imagen comprimida, ¿cómo hace PNG sin pérdidas?

¿Obtengo un comportamiento sin pérdidas solo cuando configuro el parámetro de compresión en 9?

pkout
fuente
40
La mayoría de los algoritmos de compresión sin pérdida tienen parámetros ajustables (como el tamaño del diccionario) que se generalizan en un control deslizante de "cuánto esfuerzo se debe hacer para minimizar el tamaño de salida". Esto es válido para ZIP, GZip, BZip2, LZMA, ...
Daniel B
20
La pregunta podría formularse de manera diferente. Si no se pierde calidad de la compresión, ¿por qué no usar siempre la compresión que produce el tamaño más pequeño? La respuesta entonces sería, porque requiere más RAM y más tiempo de CPU para comprimir y descomprimir. A veces quieres una compresión más rápida y no te importa tanto la relación de compresión.
kasperd
14
La compresión PNG es casi idéntica a los archivos ZIP. Puede comprimirlos más o menos, pero recupera el archivo exacto cuando se descomprime; eso es lo que lo hace sin pérdidas.
mikebabcock
13
La mayoría de los programas de compresión como Zip y Rar le permiten ingresar el "nivel de compresión" que le permite elegir entre archivos más pequeños <--> menos tiempo. No significa que este software descarte datos durante la compresión. Esta configuración (en GIMP, pngcrush, etc.) es similar.
Salman A
2
@naxa: No hay advertencias sobre cuán sin pérdidas es realmente el png. Siempre es 100% sin pérdidas. El artículo solo le advierte sobre los errores que algunos navegadores antiguos tenían en su implementación PNG para manejar la corrección gamma. Y eso solo es significativo si necesita hacer coincidir el color con los colores CSS (que no están corregidos por gamma).
Pauli L

Respuestas:

184

PNG no tiene pérdidas. Lo más probable es que GIMP simplemente no esté usando la mejor palabra en este caso. Piense en ello como "calidad de compresión", o en otras palabras, "nivel de compresión". Con una compresión más baja, obtienes un archivo más grande, pero lleva menos tiempo producirlo, mientras que con una compresión más alta, obtienes un archivo más pequeño que tarda más en producirse. Por lo general, obtiene rendimientos decrecientes (es decir, no una disminución de tamaño tan grande en comparación con el aumento en el tiempo que se necesita) al subir a los niveles de compresión más altos, pero depende de usted.

jjlin
fuente
42
Además, la compresión PNG tiene muchos parámetros ajustables donde los ajustes en cualquier dirección pueden reducir el tamaño de salida dependiendo del contenido de la fuente; es mucho más complejo que un simple control deslizante "mejor" y "peor". Para fines generales, no es demasiado importante, pero si desea el más pequeño absoluto, use una herramienta como pngcrushesa para comparar muchas variaciones para el más pequeño posible.
Bob
44
Un nivel de compresión más alto aumenta el tiempo de compresión, pero ¿también afecta la descompresión ?
Nolonar
10
@Nolonar Generalmente no; en todo caso, un nivel de compresión más alto generalmente disminuye el tiempo de descompresión porque hay menos datos para que tenga que leer y procesar. El mayor tiempo de compresión se debe a hacer un trabajo más completo de encontrar patrones para comprimir (simplificar demasiado).
esponjoso
1
La respuesta de @fluffy LordNeckbeard hizo que la compresión más alta tardara 5 veces más en decodificarse que la más baja.
André Chalella
1
Para PNG, es bastante común tener un tiempo de descompresión más largo para archivos mejor comprimidos. El problema es que con PNG, un posible truco es aplicar el algoritmo de compresión una y otra vez siempre que el archivo se haga más pequeño. Una vez que aumenta el tamaño, deja de aplicarlo. Por lo tanto, es bastante posible que aplique el algoritmo de compresión 5 o 6 veces, lo que significa que debe descomprimir el archivo 5 o 6 veces para mostrar la imagen.
yo '
213

PNG está comprimido, pero sin pérdidas

El nivel de compresión es una compensación entre el tamaño del archivo y la velocidad de codificación / decodificación. Para generalizar demasiado, incluso los formatos que no son de imagen, como FLAC, tienen conceptos similares.

Diferentes niveles de compresión, misma salida decodificada

Aunque los tamaños de archivo son diferentes, debido a los diferentes niveles de compresión, la salida decodificada real será idéntica.

Puede comparar los valores hash MD5 de las salidas decodificadas con el ffmpeguso del silenciador MD5 .

Esto se muestra mejor con algunos ejemplos:

Crear archivos PNG:

$ ffmpeg -i input -vframes 1 -compression_level 0 0.png
$ ffmpeg -i input -vframes 1 -compression_level 100 100.png
  • Por defecto ffmpegse utilizará -compression_level 100para la salida PNG.

Comparar el tamaño del archivo:

$ du -h *.png
  228K    0.png
  4.0K    100.png

Decodifica los archivos PNG y muestra hashes MD5:

$ ffmpeg -loglevel error -i 0.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

$ ffmpeg -loglevel error -i 100.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

Como ambos hashes son iguales, puede estar seguro de que las salidas decodificadas (el video sin comprimir) son exactamente las mismas.

lema
fuente
26
+1 no sabía que ffmpeg podía manejar pngs.
Lekensteyn
21
@Lekensteyn Es genial para hacer capturas de pantalla . Ejemplo para saltear 30 segundos y tomar una captura de pantalla: ffmpeg -ss 30 -i input -vframes 1 output.pngTambién es bueno para hacer videos con imágenes y viceversa.
llogan
¿Significa que el PNG debe descomprimirse cada vez que debe renderizarse? Porque si eso es cierto, debemos serlo
Akshay2000
Si vuelve a leer el archivo desde el disco o la memoria caché, sí, debe descomprimirse. Sin embargo, dentro de la misma página, el caché probablemente puede reutilizar la versión descomprimida.
David Mårtensson
1
@ akshay2000 Depende de cómo funciona el programa que representa el PNG. Por lo general, el archivo se lee desde el disco, se descomprime y se almacena en la memoria RAM. Por lo tanto, siempre que esté almacenado en la RAM, no necesitará descomprimir la imagen nuevamente.
xZise
24

La compresión PNG ocurre en dos etapas.

  1. La precompresión reorganiza los datos de la imagen para que sea más compresible mediante un algoritmo de compresión de uso general.
  2. La compresión real se realiza mediante DEFLATE, que busca y elimina secuencias de bytes duplicadas al reemplazarlas con tokens cortos.

Dado que el paso 2 es una tarea que requiere mucho tiempo / recursos, la biblioteca zlib subyacente (encapsulación de DEFLATE sin procesar) toma un parámetro de compresión que va desde 1 = compresión más rápida, 9 = mejor compresión, 0 = sin compresión. De ahí proviene el rango 0-9, y GIMP simplemente pasa ese parámetro a zlib. Observe que en el nivel 0 su png en realidad será un poco más grande que el mapa de bits equivalente.

Sin embargo, el nivel 9 es solo el "mejor" que zlib intentará, y sigue siendo una solución de compromiso .
Para tener una idea real de esto, si está dispuesto a gastar 1000 veces más potencia de procesamiento en una búsqueda exhaustiva, puede obtener una densidad de datos 3-8% más alta usando zopfli en lugar de zlib.
La compresión sigue sin pérdidas, es solo una representación DEFLATE más óptima de los datos. Esto se acerca a los límites de las bibliotecas compatibles con zlib y, por lo tanto, es la verdadera "mejor" compresión que es posible lograr usando PNG.

Adria
fuente
2
Nota: El tiempo de descompresión es el mismo independientemente del nivel de compresión o el recuento de iteraciones cuando se usa zopflipng.
Adria
16

Una motivación principal para el formato PNG era crear un reemplazo para GIF que no solo fuera gratuito sino también una mejora sobre él en todos los aspectos. Como resultado, la compresión PNG es completamente sin pérdidas, es decir, los datos de la imagen original se pueden reconstruir exactamente, bit por bit, al igual que en GIF y la mayoría de las formas de TIFF.

PNG utiliza un proceso de compresión de 2 etapas:

  1. Precompresión: filtrado (predicción)
  2. Compresión: DEFLATE (ver wikipedia )

El paso de precompresión se llama filtrado, que es un método de transformación reversible de los datos de imagen para que el motor de compresión principal pueda funcionar de manera más eficiente.

Como un ejemplo simple, considere una secuencia de bytes que aumenta uniformemente de 1 a 255:

1, 2, 3, 4, 5, .... 255

Como no hay repetición en la secuencia, se comprime muy mal o nada en absoluto. Pero una modificación trivial de la secuencia, es decir, dejar solo el primer byte pero reemplazar cada byte posterior por la diferencia entre él y su predecesor, transforma la secuencia en un conjunto extremadamente compresible:

1, 1, 1, 1, 1, .... 1

La transformación anterior no tiene pérdidas, ya que no se omitieron bytes, y es completamente reversible. El tamaño comprimido de esta serie se reducirá mucho, pero la serie original aún se puede reconstituir perfectamente.

Los datos de imagen reales rara vez son tan perfectos, pero el filtrado mejora la compresión en imágenes en escala de grises y color verdadero, y también puede ayudar en algunas imágenes de paleta. PNG admite cinco tipos de filtros, y un codificador puede elegir usar un filtro diferente para cada fila de píxeles en la imagen:

imagen

El algoritmo funciona en bytes, pero para los píxeles grandes (por ejemplo, RGB de 24 bits o RGBA de 64 bits) solo se comparan los bytes correspondientes, lo que significa que los componentes rojos de los colores de los píxeles se manejan por separado de los componentes de píxeles verdes y azules.

Para elegir el mejor filtro para cada fila, un codificador necesitaría probar todas las combinaciones posibles. Esto es claramente imposible, ya que incluso una imagen de 20 filas requeriría probar más de 95 billones de combinaciones, donde "probar" implicaría filtrar y comprimir toda la imagen.

Los niveles de compresión normalmente se definen como números entre 0 (ninguno) y 9 (mejor). Estos se refieren a compensaciones entre velocidad y tamaño, y se relacionan con cuántas combinaciones de filtros de fila se deben probar. No existen estándares con respecto a estos niveles de compresión, por lo que cada editor de imágenes puede tener sus propios algoritmos sobre cuántos filtros probar al optimizar el tamaño de la imagen.

El nivel de compresión 0 significa que los filtros no se utilizan en absoluto, lo cual es rápido pero derrochador. Los niveles más altos significan que se prueban más y más combinaciones en las filas de imágenes y solo se retienen las mejores.

Supongo que el enfoque más simple para la mejor compresión es comprimir de forma incremental cada fila con cada filtro, guardar el resultado más pequeño y repetir para la siguiente fila. Esto equivale a filtrar y comprimir la imagen completa cinco veces, lo que puede ser una compensación razonable para una imagen que se transmitirá y decodificará muchas veces. Los valores de compresión más bajos harán menos, a discreción del desarrollador de la herramienta.

Además de los filtros, el nivel de compresión también puede afectar el nivel de compresión zlib, que es un número entre 0 (sin desinflar) y 9 (desinflar máximo). La forma en que los niveles 0-9 especificados afectan el uso de los filtros, que son la principal característica de optimización de PNG, aún depende del desarrollador de la herramienta.

La conclusión es que PNG tiene un parámetro de compresión que puede reducir el tamaño del archivo de manera muy significativa, todo sin perder ni un solo píxel.

Fuentes:

Documentación de Wikipedia Portable Network Graphics
libpng Capítulo 9 - Compresión y filtrado

harrymc
fuente
1
No creo que la configuración del nivel de compresión cambie el uso de filtros. La configuración del nivel 1-9 probablemente solo elige el nivel de compresión zlib 1-9, y el nivel 0 significa que el algoritmo de desinflado no se utiliza en absoluto. La mayoría de las implementaciones probablemente no cambien los filtros por fila, sino que solo usan el filtro Path todo el tiempo.
Pauli L
@PauliL: No estoy de acuerdo, porque en todas las comparaciones del software de compresión PNG, hay diferencias muy grandes entre los tamaños de las imágenes generadas. Si todos los productos usaban los mismos parámetros para la misma biblioteca, entonces todos los tamaños deberían haber sido los mismos, así como la velocidad.
harrymc
¿Tienes algún enlace a tales comparaciones?
Pauli L
@PauliL: Se realizó una búsqueda rápida con esta comparación .
harrymc
@PauliL: Probablemente tenga razón en que los niveles de compresión de zlib se ven afectados por los niveles de compresión de PNG. He modificado mi respuesta en consecuencia, aunque ninguna herramienta de compresión documenta lo que hacen exactamente. Quizás la explicación de las herramientas con los peores resultados de tamaño es que no usan ningún filtro, solo compresión zlib.
harrymc
5

OK, llego demasiado tarde para la recompensa, pero de todos modos aquí está mi respuesta.

PNG siempre es sin pérdidas . Utiliza el algoritmo Deflate / Inflate, similar a los utilizados en los programas zip.

El algoritmo Deflate busca secuencias repetidas de bytes y las reemplaza por etiquetas. La configuración del nivel de compresión especifica cuánto esfuerzo usa el programa para encontrar la combinación óptima de secuencias de bytes, y cuánta memoria está reservada para eso. Es un compromiso entre el tiempo y el uso de la memoria frente al tamaño del archivo comprimido. Sin embargo, las computadoras modernas son tan rápidas y tienen suficiente memoria, por lo que rara vez es necesario usar otro que no sea la configuración de compresión más alta.

Muchas implementaciones PNG usan la biblioteca zlib para la compresión. Zlib tiene nueve niveles de compresión, 1-9. No conozco los aspectos internos de Gimp, pero dado que tiene configuraciones de nivel de compresión 0-9 (0 = sin compresión), asumiría que esta configuración simplemente selecciona el nivel de compresión de zlib.

El algoritmo de desinflado es un algoritmo de compresión de propósito general , no ha sido diseñado para comprimir imágenes. A diferencia de la mayoría de los otros formatos de archivo de imagen sin pérdida, el formato PNG no se limita a eso. La compresión PNG aprovecha el conocimiento de que estamos comprimiendo una imagen 2D . Esto se logra mediante los llamados filtros .

(Filtro es en realidad un término un poco engañoso aquí. En realidad no cambia el contenido de la imagen, solo lo codifica de manera diferente. Un nombre más preciso sería codificador delta).

La especificación PNG especifica 5 filtros diferentes (incluido 0 = ninguno). El filtro reemplaza los valores absolutos de píxeles con una diferencia de píxeles anteriores a la izquierda, arriba, diagonal o una combinación de ellos. Esto puede mejorar significativamente la relación de compresión. Cada línea de escaneo en la imagen puede usar un filtro diferente. El codificador puede optimizar la compresión eligiendo el mejor filtro para cada línea.

Para los detalles de formato de archivo PNG, consulte PNG especificación .

Como hay un número prácticamente infinito de combinaciones, no es posible probarlas todas. Por lo tanto, se han desarrollado diferentes tipos de estrategias para encontrar una combinación efectiva. La mayoría de los editores de imágenes probablemente ni siquiera intentan optimizar los filtros línea por línea, sino que solo usan un filtro fijo (probablemente Paeth).

Un programa de línea de comandos pngcrush intenta varias estrategias para encontrar el mejor resultado. Puede reducir significativamente el tamaño del archivo PNG creado por otros programas, pero puede tomar bastante tiempo en imágenes más grandes. Ver Source Forge - pngcrush .

Pauli L
fuente
3

El nivel de compresión en cosas sin pérdidas siempre es solo intercambiar recursos de codificación (generalmente tiempo, a veces también RAM) frente a la tasa de bits. La calidad es siempre 100%.

Por supuesto, los compresores sin pérdidas NUNCA pueden garantizar una compresión real. Los datos aleatorios son incompresibles, no hay un patrón para encontrar y no hay similitud. Teoría de la información de Shannon y todo eso. El punto principal de la compresión de datos sin pérdida es que los humanos generalmente trabajan con datos altamente no aleatorios, pero para la transmisión y el almacenamiento, podemos comprimirlos en la menor cantidad de bits posible. Con suerte, lo más cerca posible de la complejidad de Kolmogorov del original.

Ya sea datos genéricos zip o 7z, imágenes png, audio flac o video h.264 (en modo sin pérdida), es lo mismo. Con algunos algoritmos de compresión, como lzma (7zip) y bzip2, aumentar la configuración de compresión aumentará el tiempo de CPU del DECODER (bzip2) o, más a menudo, la cantidad de RAM necesaria (lzma y bzip2, y h.264 con más marcos de referencia) . A menudo, el decodificador tiene que guardar más salida decodificada en RAM porque decodificar el siguiente byte podría referirse a un byte decodificado hace muchos megabytes (por ejemplo, un cuadro de video que es más similar a uno de hace medio segundo se codificaría con referencias a 12 cuadros atrás) ) Lo mismo con bzip2 y elegir un tamaño de bloque grande, pero eso también se descomprime más lentamente. lzma tiene un diccionario de tamaño variable y puede crear archivos que requieran 1.

Peter Cordes
fuente
Hmmm, vi una implementación para tirar del control del motor paso a paso y la cabeza directamente para proporcionar una compresión sin pérdidas garantizada. La codificación Manchester es fácil de superar si tiene una fuente de reloj de alta resolución.
Joshua
@Joshua: Usar un formato de almacenamiento físico de mayor densidad no es lo mismo que la compresión de datos ...
SamB
0

En primer lugar, PNG siempre es sin pérdidas. La aparente paradoja se debe al hecho de que hay dos tipos diferentes de compresión posibles (para cualquier tipo de datos): con pérdida y sin pérdida.

La compresión sin pérdidas comprime los datos (es decir, el tamaño del archivo) usando varios trucos, manteniendo todo y sin hacer ninguna aproximación. Como resultado, es posible que la compresión sin pérdida en realidad no pueda comprimir las cosas. (Técnicamente, los datos con alta entropía pueden ser muy difíciles o incluso imposibles de comprimir para métodos sin pérdidas ). La compresión con pérdida se aproxima a los datos reales, pero la aproximación es imperfecta, pero este "desecho" de precisión permite una mejor compresión.

Aquí hay un ejemplo trivial de compresión sin pérdidas: si tiene una imagen hecha de 1,000 píxeles negros, en lugar de almacenar el valor de negro 1,000 veces, puede almacenar un conteo (1000) y un valor (negro) comprimiendo así 1000 píxeles " imagen "en solo dos números. (Esta es una forma cruda de un método de compresión sin pérdida llamado codificación de longitud de ejecución).

GregD
fuente