Blog | Archivo | Contacto | Administración |
Supongamos que queremos reducir el tamaño de varias imágenes. Es un problema ampliamente tratado, así que vamos a particularizar:
Por todo ello, haremos pruebas combinadas con diferentes formas de compresión y empaquetado (Run-Length, Huffman (siempre canónico), LZ77, Deflate, diccionario rotatorio) y ciertas transformaciones (Haar, tiles, subdivisión, algunos predictores). Dejamos fuera LZ78, LZW, y diccionarios varios cuando su tamaño se dispare.
Hagamos otra hipótesis:
Por ello es que nos compensa tratar los planos por separado, y comprimir cada uno con una técnica especializada para imágenes monocromas.
Así pues, podemos empezar a hacer pruebas para un fondo, es decir, imágenes transparente + negro. Además, eso nos da una cota superior: si el archivo comprimido ocupa Ancho*Alto/8 o más es obvio que hemos fracasado, pues es el tamaño que ocuparía empaquetando cada pixel en un bit (equivalente al caso trivial de Huffman con 2 valores, óptimo por tanto trabajando con bits completos).
Tras todas las pruebas mis conclusiones son:
Así que mis recomendaciones son:
Tipo fax (RLE y Huffman alternos).
Una forma muy usada es la compresión de los faxes: básicamente consisten en contar cuántos unos o ceros hay (run-length) y comprimir esas longitudes con códigos de Huffman (modificados). No es necesario indicar cuál es el valor que se repite pues al ser sólo dos se van alternando. Se usan árboles de Huffman distintos para las longitudes de cada valor.
En mi caso usaré árboles creados aposta para la imagen en vez de unos genéricos y no usaré códigos modificados pues no hay longitudes grandes al ser una imagen pequeña.
Debo decir que no funciona nada mal el algoritmo, es el segundo mejor de todas mis pruebas; como ejemplo:
Se comprime en 2987 bytes + diccionario aparte (las longitudes en bits de los códigos Huffman canónicos, para reconstruir los árboles / tablas). Los diccionarios van aparte por si se quieren unificar códigos en toda la aplicación, compartir, o lo que sea. Pongamos unos 40-60 bytes extras.
En cualquier caso, estamos hablando de unas 3K en una imagen cuyo límite estaba en 8K. Es decir, un 37,5% del original, que no está nada mal. Este algoritmo funciona de vicio en cualquier tipo de imágenes.
Subdivisión recursiva + Huffman.
Sin embargo, dadas mis restricciones de espacio necesito más compresión que el método anterior. Y dada la estética de mis imágenes haré otra hipótesis:
Cogemos una imagen, le ajustamos la exposición y gamma y empezamos a comprimir:
-> |
Tenemos el límite en 128x96/8=1546 bytes. El método anterior lo deja en 499 + diccionarios. Pongamos 550 bytes en total.
Empezamos extendiendo las dimensiones para que la imagen entre en un cuadrado cuyo lado sea potencia de 2. Ahora construimos un árbol cuaternario donde las hojas sean los cuadrados de color a dibujar. Es decir, sólo codificamos el color, y si un nodo no es hoja entonces no se dibuja (es de soporte). Por tanto, cada nodo se puede codificar con 4 bits indicando si tiene o no hijos en cualquiera de las 4 direcciones.
Se generan 1700 nodos (1025 hojas), empaquetando tal cual son 850 bytes. Pero no vamos a empaquetar sino aplicar huffman.
Nos quedan 534 bytes, todo incluido. Pero se puede hacer mejor: reordenemos el árbol, que se emita en orden de recorrido por anchura en vez de profundidad; de esta forma todas las hojas del último nivel (a 0) estarán juntas, y por tanto se pueden quitar asumiendo que a partir de que terminen los datos siempre se da ese valor (quedando 1065 de 1700 nodos).
Y así se queda en 433 bytes, incluyendo diccionario, flags y dimensiones (sólo necesita el Log2 del lado del cuadrado). En total un 28,19% del total, nada mal para una imagen no especialmente buena, y dejando abierta la posibilidad de comprimirse aún más (hay muchas rachas de 0's y 15's antes de pasar por Huffman).
¿Me dará para lo que quiero? No lo sé, pero ha sido entretenido.
¡Estos matemáticos son unos abusones! :P Pobre ZX xDDD
Creo que en el texto hay pruebas suficientes como para pensar que no se trata de una máquina de Sinclair. Si bien todo esto es aplicable, por supuesto. ;)
Post cerrado