Acabo de encontrar lo siguiente: puse varias copias idénticas de una imagen png en una carpeta y luego intenté comprimir esa carpeta con los siguientes métodos:
tar czf folder.tar.gz folder/
tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
(este funciona bien para imágenes idénticas, sin embargo, para imágenes similares la ganancia es cero)zip -r folder.zip folder/
Cuando me registré el tamaño de la .tar.gz
, .tar.xz
, .zip
me di cuenta de que es casi el mismo que el de folder/
.
Entiendo que una imagen png en sí misma puede tener un alto nivel de compresión y, por lo tanto, no se puede comprimir más. Sin embargo, al combinar muchas imágenes png similares (en este caso, incluso idénticas) en un archivo comprimido y luego comprimir el archivo, esperaría que el tamaño requerido disminuya notablemente. En el caso de imágenes idénticas, esperaría un tamaño aproximadamente del tamaño de una sola imagen.
data-compression
un invitado
fuente
fuente
.bmp
), el archivo tar.gz debería poder aprovechar la similitud. (Al menos si la similitud es que muchos píxeles son idénticos)Respuestas:
Eche un vistazo a cómo funcionan los algoritmos de compresión. Al menos aquellos en la familia Lempel-Ziv (
gzip
usa LZ77 ,zip
aparentemente también lo hace , yxz
usa LZMA ) comprimen algo localmente : no se pueden identificar similitudes que se encuentren muy alejadas entre sí.Los detalles difieren entre los métodos, pero la conclusión es que cuando el algoritmo alcanza la segunda imagen, ya ha "olvidado" el comienzo de la primera. Y así.
Puede intentar cambiar manualmente los parámetros del método de compresión; si el tamaño de la ventana (LZ77) resp. el tamaño de bloque / fragmento (métodos posteriores) es al menos tan grande como dos imágenes, probablemente verá más compresión.
Tenga en cuenta que lo anterior solo se aplica realmente si tiene imágenes idénticas o imágenes sin comprimir casi idénticas . Si hay diferencias, las imágenes comprimidas pueden no parecerse en la memoria. No sé cómo funciona la compresión PNG; es posible que desee verificar las representaciones hexadecimales de las imágenes que tiene para las subcadenas compartidas manualmente.
También tenga en cuenta que incluso con parámetros modificados y redundancia para explotar, no podrá reducir el tamaño de una imagen. Los diccionarios más grandes significan un tamaño de palabra de código más grande, e incluso si dos imágenes son exactamente idénticas, es posible que deba codificar la segunda usando varias palabras de código (que apuntan a la primera).
fuente
Por qué sucede esto En realidad, hay dos efectos diferentes que ocurren aquí:
Cada archivo comprimido de forma independiente. Algunos programas de archivo, incluido zip, comprimen cada archivo de forma independiente, sin memoria de un archivo a otro. En otras palabras, cada archivo se comprime por separado, luego los archivos comprimidos se concatenan en un archivo.
Memoria de corto plazo. Algunos programas de archivo pueden usar información sobre un archivo para ayudar a comprimir mejor el siguiente archivo. Efectivamente concatenan los archivos, luego comprimen el resultado. Esto es una mejora
Ver también la respuesta de Nayuki para más discusión sobre esto.
Sin embargo, hay un segundo problema. Algunos esquemas de compresión, incluidos zip, gzip y bzip2, tienen una memoria limitada. Comprimen los datos sobre la marcha y recuerdan los últimos 32 KB de datos, pero no recuerdan nada sobre los datos que ocurrieron mucho antes en el archivo. En otras palabras, no pueden encontrar datos duplicados si los duplicados se producen a más de 32 KB de distancia. Como resultado, si los archivos idénticos son cortos (más cortos que aproximadamente 32 KB), el algoritmo de compresión puede eliminar los datos duplicados, pero si los archivos idénticos son largos, el algoritmo de compresión se manguera y pierde valor: no puede detectar ninguno de El duplicado en sus datos. (Bzip recuerda los últimos 900 KB de datos, en lugar de 32 KB).
Todos los algoritmos de compresión estándar tienen un tamaño de memoria máximo, más allá del cual no pueden detectar patrones ... pero para algunos, este número es mucho mayor que otros. Para Bzip, es algo así como 900 KB. Para xz, es algo así como 8 MB (con la configuración predeterminada). Para 7z, es algo así como 2GB. 2 GB es más que suficiente para reconocer las copias duplicadas de archivos PNG (que suelen ser mucho más pequeños que 2 GB). Además, 7z también trata de ser inteligente al colocar archivos que probablemente sean similares entre sí en el archivo, para ayudar al compresor a funcionar mejor; tar no sabe nada de eso.
Véase también la respuesta de Rafael y la respuesta de Nayuki para más explicación de este efecto.
Cómo se aplica esto a su entorno. Para su ejemplo específico, está trabajando con imágenes PNG. Las imágenes PNG están comprimidas, por lo que puede pensar en cada archivo PNG como básicamente una secuencia de bytes de aspecto aleatorio, sin patrones ni duplicación dentro del archivo. No hay nada que pueda explotar un compresor si mira una sola imagen PNG. Por lo tanto, si intenta comprimir un solo archivo PNG (o crear un archivo zip / tar / ... que contenga solo un archivo PNG), no obtendrá ninguna compresión.
Ahora veamos qué sucede si intentas almacenar varias copias del mismo archivo PNG:
Archivos pequeños. Si el archivo PNG es muy pequeño, entonces todo, excepto zip, funcionará muy bien. Zip fallará espectacularmente: comprime cada archivo de forma independiente, por lo que no tiene posibilidad de detectar la redundancia / duplicación entre los archivos. Además, al intentar comprimir cada archivo PNG, no logra compresión; El tamaño de un archivo zip será enorme. Por el contrario, el tamaño de un archivo tar (ya sea comprimido con gzip, bzip2 o xz) y un archivo 7z será pequeño, ya que básicamente almacena una copia del archivo y luego se da cuenta de que los demás son idénticos: se benefician de retener memoria de un archivo a otro.
Archivos grandes. Si el archivo PNG es grande, solo 7z funciona bien. En particular, el zip continúa fallando espectacularmente. Además, tar.zip y tar.bzip2 fallan gravemente, ya que el tamaño del archivo es mayor que la ventana de memoria del compresor: como el compresor ve la primera copia del archivo, no puede reducirlo (ya que ya se ha comprimido ); cuando comienza a ver el comienzo de la segunda copia del archivo, ya ha olvidado las secuencias de bytes que se ven al principio del primer archivo y no puede establecer la conexión de que estos datos son en realidad un duplicado.
Por el contrario, tar.xz y 7z continúan haciendo un gran trabajo con múltiples copias de un archivo PNG grande. No tienen la limitación de "tamaño de memoria pequeño" y pueden notar que la segunda copia del archivo es idéntica a la primera copia, por lo que no es necesario almacenarla por segunda vez.
Qué puedes hacer al respecto. Use 7z. Tiene un montón de heurísticas que ayudarán a detectar archivos idénticos o similares y comprimir realmente bien en ese caso. También puede mirar lrzip con compresión lzop.
¿Cómo puedo saber? Pude verificar esto probando algunos experimentos con 100 copias de un archivo que contiene bytes aleatorios. Intenté 100 copias de un archivo de 4KB, 100 copias de un archivo de 1 MB y 100 copias de un archivo de 16 MB. Esto es lo que encontré:
Como puede ver, zip es horrible, no importa cuán pequeño sea su archivo. 7z y xz son buenas si sus imágenes no son demasiado grandes (pero xz será frágil y dependerá del orden en que se coloquen las imágenes en el archivo, si tiene algunos duplicados y algunos no duplicados mezclados). 7z es bastante bueno, incluso para archivos grandes.
Referencias Esto también se explica bien en un montón de publicaciones en Super User. Echar un vistazo:
fuente
tar
ellos y luego comprimir conxz
(que funcionó muy bien para imágenes idénticas) sin embargo, en el caso de imágenes similares, la ganancia es cero. Intenté con 71 imágenes cada una con un tamaño de ~ 831 KB.En primer lugar, tenga en cuenta que el formato de imagen PNG es básicamente píxeles RGB sin procesar (con algo de filtrado de luz) empujado a través del formato de compresión DEFLATE. En términos generales, los archivos comprimidos (PNG, JPEG, MP3, etc.) no verán ningún beneficio si se comprimen nuevamente. Entonces, para propósitos prácticos, podemos tratar su archivo PNG como datos aleatorios incompresibles para el resto del experimento.
Segundo, tenga en cuenta que los formatos ZIP y gzip también usan el códec DEFLATE. (Esto explicaría por qué comprimir o comprimir un solo archivo producirá esencialmente el mismo tamaño de salida).
Ahora permítame comentar cada caso de prueba individualmente:
tar czf folder.tar.gz folder/
Esto crea un archivo TAR (sin comprimir) que concatena todos sus archivos PNG idénticos (con una pequeña cantidad de metadatos y relleno añadido). Luego, este único archivo se envía a través del compresor gzip para crear un archivo de salida comprimido.
Desafortunadamente, el formato DEFLATE solo admite una ventana de diccionario LZ77 de 32768 bytes. Entonces, aunque el TAR contiene datos repetitivos, si su archivo PNG es mayor que 32 KiB, entonces el compresor DEFLATE no puede recordar datos lo suficientemente atrás como para aprovechar el hecho de que se repiten datos idénticos.
Por otro lado, si vuelve a intentar este experimento con, por ejemplo, un archivo PNG de 20 KB duplicado 10 veces, es muy probable que obtenga un archivo gzip solo un poco más grande que 20 KB.
tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
Esto crea un archivo TAR como antes, y luego usa el formato xz y el compresor LZMA / LZMA2. No pude encontrar información sobre LZMA en esta situación, pero desde 7-Zip para Windows sé que puede admitir grandes tamaños de ventana de diccionario (por ejemplo, 64 MiB). Por lo tanto, es posible que esté utilizando configuraciones subóptimas y que el códec LZMA haya podido reducir el archivo TAR al tamaño de un archivo PNG.
zip -r folder.zip folder/
El formato ZIP no admite archivos "sólidos"; es decir, cada archivo se comprime de forma independiente. Asumimos que cada archivo es incompresible. Por lo tanto, el hecho de que cada archivo sea idéntico no puede ser explotado, y el archivo ZIP será tan grande como la concatenación directa de todos los archivos.
fuente
xz
por defecto se ejecuta enxz -6
modo, que utiliza un diccionario 8 MiB LZMA2 . No pude encontrar de inmediato en la página man disponible en mi sistema Debian cuál es el tamaño de ventana predeterminado para el compresor.tar czf folder.tar.gz folder/ && xz --stdout folder.tar.gz > folder.tar.gz.xz
sin ningún efecto (lo cual tiene sentido de acuerdo con lo que explicaste). Supongo que me perdí un poco en todas estas cosas de compresión: D Cuando lo usotar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
, en realidad termino con un poco más del tamaño de una imagen (lo que también tiene sentido según el tamaño predeterminado de la ventana dict de 64 MiB). Actualicé mi pregunta en consecuencia. ¡Gracias!tar -> gzip -> xz
, el gzip DEFLATE podría comprimir cada copia de los datos PNG de una manera diferente, por lo que xz no podrá detectar las redundancias.El problema es que (la mayoría) de los esquemas de compresión carecen del conocimiento sobre los datos que tiene. Incluso si descomprime sus PNG en mapas de bits y los comprime en el tarball, no obtendrá resultados (significativamente) más pequeños.
En el caso de muchas imágenes similares, un esquema de compresión apropiado sería un códec de video.
Con la codificación sin pérdidas, debe lograr el resultado de compresión casi perfecto que espera.
Si quieres probarlo, usa algo como esto:
https://trac.ffmpeg.org/wiki/Create%20a%20video%20slideshow%20from%20images
fuente
PNG es la combinación de Filtros + LZ77 + Huffman (la combinación de LZ77 + Huffman se llama Deflate) en ese orden:
paso 1) si el filtro es diferente de Ninguno, el valor de los píxeles se reemplaza por la diferencia de los píxeles adyacentes (para obtener más detalles, consulte http://www.libpng.org/pub/png/book/chapter09.html ) . Eso aumenta la compresión de imágenes con gradientes (entonces ... 4 5 6 7 se convierte en ... 1 1 1 1) y puede ayudar en áreas del mismo color (... 3 3 3 5 5 5 5 5 se convierte en 0 0 0 2 0 0 0 0 0). Por defecto, los filtros están habilitados en imágenes de 24 bits y deshabilitados en imágenes de 8 bits con una paleta.
paso 2) los datos se comprimen con LZ77 que reemplaza cadenas repetidas (coincidencias) de bytes con una tupla que contiene la distancia a la coincidencia y la longitud de la coincidencia.
paso 3) el resultado del paso 2 se codifica con el código Huffman que reemplaza los símbolos de longitud fija con códigos de longitud variable, cuanto más frecuente sea el símbolo, más corto será el código.
Hay múltiples problemas:
Un pequeño cambio que afecta a pocos píxeles dará como resultado cambios en los resultados de los 3 pasos de la compresión png:
1) El valor filtrado de los píxeles adyacentes cambiará (según el filtro utilizado). Eso amplificará los efectos de pequeños cambios.
2) El cambio significará que las coincidencias con esa área serán diferentes. Por ejemplo, cambiar 333333 a 333533 hace que otra aparición de 333333 ya no coincida, por lo que seleccionará otra coincidencia a 333333 con una distancia diferente o seleccionará la misma coincidencia pero con una longitud más corta y luego otra coincidencia para los últimos 3 bytes. Por sí solo eso cambiará mucho los resultados.
3) El problema más grande está en el paso 3. El código huffman usa un número variable de bits, por lo que incluso un pequeño cambio dará como resultado que todo lo que sigue ya no esté alineado. AFAIK La mayoría de los algoritmos de compresión no pueden detectar coincidencias que no están alineadas en bytes, por lo que evitará (o al menos reducirá) la compresión de los datos ya comprimidos que siguen al cambio a menos que el compresor pueda detectar coincidencias que no estén alineadas en bytes.
Los otros problemas ya están cubiertos por otras respuestas:
4) Gzip usa el mismo algoritmo de desinflado con un diccionario de 32 KB, por lo que si los archivos png son más grandes que 32 KB, las coincidencias no se detectarán, incluso si son idénticas. Bzip2 es mejor en ese aspecto, ya que utiliza un bloque de 900 KB. XZ usa LZMA, que IIRC tiene un diccionario de 4 MB en el nivel de compresión predeterminado. 5) El formato Zip no utiliza compresión sólida, por lo que no comprimirá mejor archivos similares o idénticos.
Quizás los compresores de la familia PAQ o PPMD se comprimirán mejor, pero si necesita comprimir muchos archivos de imagen similares, puede considerar 3 enfoques:
1) Almacene las imágenes sin comprimir (con PNG -0 o en un formato sin compresión) y comprímalas con un compresor con un diccionario grande o un tamaño de bloque. (LZMA funcionará bien)
2) Otra opción sería mantener los filtros pero eliminar la compresión Deflate de los PNG. Eso se puede hacer, por ejemplo, con la utilidad ( AdvDef ). Luego comprime los PNG sin comprimir resultantes. Después de la descompresión, puede mantener el PNG sin comprimir o comprimirlo nuevamente con AdvDef (pero eso llevará tiempo).
Debe probar ambos enfoques para ver cuál comprime más.
3) La última opción sería convertir las imágenes png en un video, comprimirlo con un compresor de video sin pérdida como x264 sin pérdida (teniendo especial cuidado de usar el formato de color correcto) y luego, en la extracción, extraer los cuadros a imágenes png individuales. Eso se puede hacer con ffmpeg. También necesitaría mantener la asignación entre el número de fotograma y el nombre original.
Ese sería el enfoque más complejo, pero si los pngs son parte de una animación, puede ser el más efectivo. Sin embargo, necesitará un formato de video que admita transparencia si lo necesita.
Editar: También hay formato MNG si no se usa con frecuencia.
fuente
Cuando tiene conjuntos de datos especiales, utiliza algoritmos especiales, no herramientas multipropósito.
La respuesta es que las compresiones sin pérdida elegidas no están hechas para lo que haces. Nadie espera que comprima la misma imagen dos veces, e incluso si lo hace (por accidente), comprobar todas las entradas anteriores haría que su algoritmo O (n ^ 2) (tal vez sea un poco mejor, pero el enfoque ingenuo al menos sería n ^ 2)
La mayoría de sus programas de compresión que probó en ejecución en O (n), enfatizan la velocidad sobre la relación de compresión óptima. Nadie quiere ejecutar su computadora durante 5 horas solo para ahorrar unos pocos mb, especialmente en estos días. Para entradas más grandes, cualquier cosa por encima de O (n) se convierte en un problema de tiempo de ejecución.
Otro problema es el carnero. No puede acceder a cada parte de su entrada en ningún momento, cuando la entrada se vuelve lo suficientemente grande. Incluso sin tener en cuenta esto, la mayoría de las personas no quieren renunciar a toda su memoria RAM o CPU solo para comprimir algo.
Si tiene patrones en sus archivos que desea comprimir, tendrá que realizar operaciones manuales en ellos, escribir su propia compresión o potencialmente usar una compresión de tipo "archivo" (nano). Una compresión para almacenamiento a largo plazo, que es demasiado lenta para el uso diario.
Otra opción podría ser una compresión de video sin pérdidas.
fuente
El formato de archivo PNG ya usa internamente el algoritmo de compresión DEFLATE. Este es el mismo algoritmo utilizado por xz, gzip y zip, solo que en algunas variaciones.
tar.gz
ytar.xz
aproveche la similitud entre archivos, quezip
no lo hace.Por lo tanto, de hecho, realiza la compresión DEFLATE sobre los archivos comprimidos DEFLATE; es por eso que los archivos mantienen casi el tamaño original.
El
bzip2
programa (también un algoritmo relacionado) es mejor cuando se trata de archivos (casi) idénticos.fuente
bzip2
atrapa:tar -cjf archive.tar.bz2 *.png
. Actualizado en mi respuesta.