Sie sind auf Seite 1von 11

Compresión de datos utilizando el

algoritmo LZ77: Fundamentos y


programa de aplicación
Gisella Luisa Elena Maquén Niño
gmaquenn@unprg.edu.pe
Carlos Alberto Valdivia Salazar
cvaldivia@crece.uss.edu.pe

Resumen otro archivo cuyo tamaño es menor, pero sin perder


La presente investigación tiene como objetivo analizar los información con relación al archivo original. Del mismo
fundamentos del algoritmo de compresión de datos modo, el descompresor toma como entrada el archivo
Lempel-Ziv y explicar su funcionamiento a través de un comprimido que fue generado por el compresor, y produce
programa desarrollado en el lenguaje de programación el archivo original.
C#. El LZ77 es un algoritmo de compresión de datos
perteneciente a la familia de compresores sin pérdida, El problema principal de la compresión de datos es
también llamados compresores de texto, permitiéndonos producir una secuencia binaria más corta que la empleada
ahorrar espacio de almacenamiento en el disco duro y así por el archivo original en su representación de bytes.
optimizar el uso de este recurso básico en la computadora Clásicamente, cada carácter es representado internamente
e incluso en dispositivos móviles como smartphone o con una cadena de 8 bits en base a un estándar siendo la
tablet. Este algoritmo es muy usado porque es fácil de tabla ASCII la más conocida hoy en día, La codificación
implementar y bastante eficiente en una relación ASCII es un típico ejemplo de codificación binaria de
costo/beneficio. Las variantes del algoritmo LZ77 como longitud fija: a cada carácter o símbolo que se quiere
el LZW formo la base de varios esquemas de compresión codificar se le asocia una cadena de bits de la misma
ubicuos, incluyendo el formato GIF y el algoritmo longitud (8 bits). Así, si un mensaje o texto tiene un total
“deflate” utilizado en el formato png y zip. A pesar del de x caracteres, la conversión a binario de ese mensaje
atractivo en las variantes, no las estudiaremos aquí insumirá indefectiblemente un total de 8*x bits.
porque, desafortunadamente, se trata de algoritmos Hasta 1977, todos los algoritmos de compresión de datos
sujetos a patentes, por tanto, se estudiará al algoritmo desarrollados eran básicamente compresores estáticos, y
original que dio origen a todas esas variantes, el algoritmo fue cuando el algoritmo LZ77 marca la diferencia
LZ77. buscando textos repetitivos que puedan tener una misma
Palabras clave: Compresión de datos, compresión de codificación. Los textos repetitivos son de interés, ya que
textos, algoritmo, encriptamiento, código prefijo. actualmente existen colecciones cuyos elementos son muy
similares entre sí. “Pensemos, por ejemplo, en el caso de
una colección que almacena el ADN de distintos
individuos de una misma especie, la similitud entre los
1. Introducción elementos de dicha colección será muy alta. Para explotar
“LZ77 une las iniciales de dos autores Abraham Lempel las repeticiones en este tipo de texto es que se recurre al
y Jacob Ziv, quienes en el año 1977 presentaron su parsing Lempel-Ziv 77” (Kreft & Navarro, 2017).
modelo de compresión de texto, basado en diccionario, El presente ensayo, explica el Algoritmo de Lempel Ziv,
siendo un tipo de compresión sin pérdida de datos, que no desde su fundamento teórico, su lógica de funcionamiento
omite información del archivo al comprimirlo, y es usado y su implementación, a través de un programa realizado en
cuando la información a comprimir es crítica” el lenguaje de programación C# mostrando de forma
(Wikipedia, 2018). gráfica un ejemplo de cómo se realiza la compresión y
Un compresor de datos es un programa que toma como descompresión de un mensaje y validada con la aplicación
entrada un archivo de una longitud determinada y produce desarrollada.
1
2. Compresión de datos usada a menudo para aplicaciones de compresión
de imágenes y audio (video) destinadas al
“Es un método de codificación que permite la reducción entretenimiento. Son excepciones de este tipo de
del volumen de datos tratables para representar una compresión las imágenes médicas (identificación
determinada información empleando una menor cantidad de tumores o anomalías). Los métodos de
de espacio, su característica principal es que el código compresión con pérdida logran mejores razones de
resultante tiene menor tamaño que el original y se basa compresión
fundamentalmente en buscar repeticiones en series de
datos para después almacenar solo el dato junto al número El algoritmo LZ77 se basa en un método de compresión
de veces que se repite” (EcuRed, 2017). sin pérdida de tipo substitucional que utiliza un diccionario
de datos que usan el principio de remplazar cadenas de
Un Archivo Comprimido es un archivo especial que datos con codewords que identifican a esa cadena dentro
contiene datos codificados, los cuales pueden luego ser de un diccionario (Witten, Moffat, & Bell, 1999). El
extraídos del mismo de diversas maneras consistentes en diccionario contiene una lista de subcadenas y codewords
realizar el procedimiento opuesto (descompresión). asociados a cada una de ellas. El diccionario que contiene
La redundancia depende del tipo de datos (texto, las cadenas de símbolos puede ser estático o adaptable
imágenes, sonido, etc), por tanto, no existe un método de (dinámico). Los métodos basados en diccionario, a
compresión universal que pueda ser óptimo para todos los diferencia de los métodos estadísticos, usan codewords de
tipos de datos. longitud fija y no requieren de las estadísticas de los
símbolos para realizar la compresión.
El objetivo de la compresión es siempre reducir el tamaño
de la información, intentando que esta reducción de “Prácticamente, todos los métodos de compresión
tamaño no afecte al contenido. No obstante, la reducción sustitucionales están basados en los métodos de
de datos puede afectar o no a la calidad de la información, compresión desarrollado por Abraham Lempel y Jacob
Ziv: los métodos LZ77 y LZ78” (Witten, Moffat, & Bell,
1999). En ambos métodos una subcadena es remplazada
por un apuntador a donde dicha cadena haya ocurrido
2.1. Métodos de compresión previamente en el diccionario, el cual, se crea
La compresión de datos puede dividirse en dos tipos dinámicamente. Las principales diferencias entre ellos son
principales: en como los apuntadores son representados y en las
limitaciones que imponen sobre lo que los apuntadores
 Compresión sin pérdida, es posible reconstruir pueden representar.
exactamente los datos originales D dado D’. Al
proceso de reconstrucción se le denomina
descompresión. La compresión de datos sin 3. El algoritmo LZ77
pérdida es comúnmente usada en aplicaciones
como compresión de texto, donde la pérdida de Este algoritmo, expuesto por Lempel y Ziv (1977), se
un solo bit de información es inaceptable. Los aprovecha de secuencias repetidas en los datos de entrada.
métodos de compresión sin pérdida pueden Una cadena de longitud variable de símbolos de la entrada
clasificarse en dos tipos: substitucionales (o es substituida por palabras código de tamaño fijo (una
basados en diccionario) y estadísticos. La referencia a la ocurrencia anterior de esa secuencia). El
principal distinción entre ambos es que, en el tamaño de esta palabra código es el límite de la ventana (el
caso de los métodos estadísticos, la codificación número de símbolos previamente vistos que el algoritmo
de un símbolo se basa en el contexto en el que puede referir).
este ocurre, mientras que los métodos
substitucionales agrupan símbolos creando un El método LZ77 (Lempel & Ziv, 1977) usa como
tipo de contexto implícito. diccionario parte de la información previamente leída. El
codificador mantiene una ventana al archivo de entrada y
 Compresión con pérdida, la descompresión recorre la entrada en esa ventana de derecha a izquierda
produce solamente una aproximación D* a los tantas veces como cadenas de símbolos son codificadas. La
datos originales D. La compresión con pérdida es ventana se divide en dos partes, la parte de la izquierda se
2
llama buffer de búsqueda y es el diccionario actual; la  Literales: son simplemente bytes sin comprimir.
parte de la derecha se llama buffer hacia el frente y
contiene símbolos aun no codificados (figura 1).  Palabras clave: en nuestro caso son pares
tamaño/desplazamiento.

 Banderas: simplemente nos indican si los datos que


hay a continuación son literales o palabras clave.

Para la codificación, inicialmente, el buffer de búsqueda


puede rellenarse con algún símbolo inicial mientras que el
buffer hacia el frente se rellena con los primeros símbolos
del archivo de entrada. En la práctica, el buffer de
Figura 1:Diccionario en el algoritmo LZ77
búsqueda es de algunos cientos de bytes mientras que el
3.1. Lógica de funcionamiento buffer hacia el frente es de decenas de bytes.

En este algoritmo el codificador analiza el texto como una El decodificador es más simple que el codificador. El
secuencia de caracteres, mediante una ventana deslizable decodificador debe mantener una ventana de igual tamaño
compuesta por dos partes; un buffer hacia el frente que es que la ventana de búsqueda empleada en el codificador. Al
la opción que está a punto de ser codificada y un buffer principio, este buffer es rellenado con el mismo símbolo
de búsqueda (la ventana en sí), que es la parte dónde se empleado para rellenar el buffer inicialmente en el
buscan secuencias iguales a las existentes en el buffer de codificador.
anticipación. Para codificar el contenido, o parte de él, del
El método LZ77 no requiere de las frecuencias de
buffer de anticipación, se busca la secuencia igual en el
ocurrencia de los símbolos presentes en los datos que se
buffer de búsqueda y la codificación resulta en indicar
van a comprimir. El método solo busca patrones de
esta repetición como una tripleta [offset, longitud,
subcadena en el buffer de búsqueda que ocurran en el
carácter siguiente]. Donde:
buffer hacia el frente, suponiendo que dichos patrones
 Offset es la distancia desde el principio del buffer ocurren continuamente, al menos dentro de la subcadena
de anticipación hasta el comienzo de la secuencia que engloban ambos buffers. Si esta suposición se cumple
repetida. en el conjunto de datos que se va a comprimir, el método
logra buenas razones de compresión.
 Longitud es la cantidad de caracteres repetidos.
A continuación, se muestra el algoritmo de codificación en
 Carácter siguiente es el símbolo siguiente a la LZ77 que muestra la secuencia de pasos de como funciona
secuencia en el buffer de anticipación. teóricamente el proceso de compresión de datos:
Pero, ¿cómo sabe el descompresor si lo que lee es un par
desplazamiento/tamaño o un byte sin comprimir?. La  Guardar el tamaño del archivo a comprimir.
respuesta es simple, usamos un prefijo, un bit que actúa  Repetir hasta que no haya más bytes para
como una bandera, de forma similar a un interruptor con comprimir.
dos estados que nos permite saber qué tipo de datos  Escanear el buffer hacia el frente comenzando en
vienen a continuación. Si el prefijo es 0, entonces lo que posición_actual-tamaño_de_ventana_corrediza
viene es un byte sin comprimir. Si, por el contrario, el hasta el byte actual que estamos comparando.
prefijo es 1, entonces lo que sigue a continuación es un (Notar que el descompresor no puede copiar bytes
par desplazamiento/tamaño. A estos prefijos también se de una posición desde donde sus bytes no han sido
les llama “banderas”. El par desplazamiento/tamaño es previamente definidos).
llamado una palabra clave. Una palabra clave es un grupo  ¿Hemos encontrado un byte igual al actual?
de bits (o bytes) que contienen alguna clase de
 Caso Si:
información usada por el compresor y el descompresor.
o Comparamos el siguiente byte desde la
La otra salida posible de LZ77 es un literal, la cual es
posición actual con el byte en la posición
simplemente un byte sin comprimir, de manera que la
siguiente de donde encontramos un byte igual
salida de LZ77 puede ser de tres formas:
3
al primero. La primera fila de la tabla 1indica la posición dentro del
o Continuar comparando hasta que buffer y la segunda su contenido. Consideraremos la
encontremos un byte que no es igual. posición más a la izquierda como posición 1
o Se ha encontrado un byte que no es igual. ¿Es Supongamos también que los tres primeros elementos,
el número de bytes mayor que tres? 001, ya han sido codificados; en este momento nos da igual
 Caso Si: que hayan sido comprimidos o tomados como literales.
o Escribir el desplazamiento del PRIMER byte Posteriormente nos ocuparemos de ese aspecto, pero ahora
hallado y el número de bytes repetidos tenemos que codificar lo que sigue: 01011. Llamaremos a
(tamaño). la secuencia ya codificada secuencia 1 y a la que será
o Movemos el puntero a la posición con el codificada ahora secuencia 2.
número de bytes repetidos (porque no los Si a alguien le pedimos que encuentre en 01011 una
hemos “salvado”) y seguimos buscando. secuencia que esté repetida a partir de lo que ya hemos
o También se escribe una bandera 1. codificado (001), nos dirá que los dos primeros elementos
 Caso No: de la secuencia a codificar (posiciones 4 y 5 dentro del
o Continúa la búsqueda. buffer) son iguales a los dos últimos de 001 (posiciones 2
 Caso No: y 3), y que ahí hay una repetición. Y tendrá razón, pero la
o Si no se encuentra ninguna coincidencia, genialidad de LZ está en darse cuenta de que se puede ir
simplemente se escribe un byte sin comprimir más allá y utilizar la propia secuencia a codificar como
(también se escribe un literal si no hay datos lugar donde seguir buscando repeticiones, a pesar de que
en la ventana corrediza). aún no se haya codificado.
o Debe recordar poner la bandera a 0. Veamos la secuencia 2 empieza por 0101 (posiciones 4 a
7). Si empezamos a mirar en lo que ya hemos codificado,
Por otra lado, se muestra el algoritmo de decodificación la secuencia 1, tenemos que finaliza en 01, pero si
en LZ77 que muestra la secuencia de pasos de cómo seguimos entrando en la secuencia 2 ahora veremos que
funciona teóricamente el proceso de descompresión de empieza por 01. Si juntamos el final de la secuencia 1 con
datos: el principio de la secuencia 2, tenemos 0101, que es igual
al comienzo de la secuencia a codificar o secuencia 2. Es
 Se lee el tamaño del archivo sin comprimir. decir: los elementos 4, 5, 6 y 7 de la secuencia total son
 Se repite hasta que se ha descomprimido todo una "repetición'' de los elementos 2, 3, 4 y 5. Por tanto se
el archivo. codificarán como un puntero a la posición número 2 más
 Se lee un bit (la bandera). una longitud de 4.
 Si es 0: La codificación se lleva a cabo introduciendo los datos
o Se leen 8 bits, se escriben al buffer de salida dentro de un buffer de una longitud prefijada, n, dentro del
(recordar que son un byte descomprimido) y se cual se van buscando subcadenas ya repetidas haciendo
incrementa el puntero a la salida. uso del método que acabamos de explicar.
 Si es 1: Veamos otro ejemplo. Supongamos que queremos
o Se lee el desplazamiento completo (13 bits), luego codificar la secuencia S=001010210210212021021200.
el tamaño, copiar “tamaño” bytes de Por razones didácticas usaremos un buffer de longitud
“desplazamiento” a la posición actual, y añadir al
n=18 y una longitud máxima de cadena Ls de 9.
puntero a la salida “tamaño”
Inicialmente se llenan las n – Ls posiciones del buffer con
ceros, y las Ls restantes con los primeros datos de la
Se tomará como ejemplo para poder explicar los
secuencia, con lo que el buffer en la posición inicial
algoritmos la secuencia S=00101011. Pongámoslo
quedaría como se ve en la tabla 2.
tabulado, de forma que podamos hacer referencia a cada
elemento de la secuencia fijándonos en el orden en el que 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1
aparece dentro de esta. 0 1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 s 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 1 0

s 0 0 1 0 1 0 1 1 n - Ls Ls
Secuencia 2 Tabla 2: Estado Inicial de compresión del segundo ejemplo
Secuencia 1
Tabla 1: Buffer con la secuencia de datos del primer ejemplo
4
La extensión reproducible de Ls, empezando a buscar en 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1
0 1 2 3 4 5 6 7 8
la parte ya "codificada" (las n-Ls primeras posiciones del
s 2 1 0 2 1 0 2 1 2 0 2 1 0 2 1 2 0 0
buffer), aparece en gris. La primera subcadena a codificar
se formará a partir de esa extensión reproducible, 00, n - Ls Ls
seguida del siguiente elemento que ya no está repetido 1, Tabla 5: Tercera iteración de compresión del segundo ejemplo
luego S1=001. La palabra código que representa a esa
Por último, tras desplazar las 8 posiciones que ocupa S3,
subcadena será, por convenio y en ese orden, el puntero
se obtiene S4=021021200 y C4=280 (Tabla 5).
al comienzo de la repetición menos 1, seguido de la
Comprobemos que la secuencia comprimida
longitud de la repetición, seguido del elemento final, que
C=821732672280 puede decodificarse unívocamente
no entraba en la repetición. Es decir, para este caso:
dando como resultado la secuencia original
C1=021.
S=001010210210212021021200. Es importante darse
Puesto que S1 tenía longitud 3, todo el contenido del
cuenta de que, si bien la longitud de las subcadenas no es
buffer es desplazado hacia la izquierda 3 posiciones.
fija (aunque sí limitada), la de las palabras código (C) sí lo
Posteriormente, seguiremos buscando a partir de la
es: en este caso, 3 caracteres. Esto permite separar la
posición 10 la extensión reproducible. Se grafica en la
palabra código de forma simple. Incluso dentro de una
tabla 3.
1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1 misma palabra código, los tamaños asignados a una u otra
0 1 2 3 4 5 6 7 8 función (posición a partir de la que empieza una repetición,
s 0 0 0 0 0 0 0 0 1 0 1 0 2 1 0 2 1 0 longitud de esta y elemento siguiente a ella), son también
Ls fijos, y fácilmente separables,
n - Ls
Tabla 3: Primera iteración de compresión del segundo ejemplo
La longitud de cada uno de estos campos, y de la palabra
código como suma de todos ellos, está directamente
relacionada con el tamaño del buffer, n, y con el de la
Aquí, la extensión periódica de los elementos a partir de máxima subcadena, Ls. Para descomprimir se emplea un
la posición 10 se haya en la posición 8. Empezando tanto buffer de longitud n-Ls donde se van guardando los
por 8 como por 10 encontramos la secuencia 010, así que símbolos descodificados. Inicialmente el buffer se pone
S2 es la parte que se repite del comienzo de Ls, 010 todo a 0.
(posiciones 10 a 12), más el siguiente elemento, 2, que ya Seguidamente se van leyendo una por una las palabras
no se repite (posición 13). Luego S2=0102, que se código, lo cual puede hacerse sin especial cuidado al tener
codifica como C2=732. Desplazamos 4 posiciones a la la misma longitud. También en este caso ilustraremos la
izquierda, que es lo que mide S2, y la "repetición'' de la descompresión paso por paso. La primera iteración se
secuencia Ls se encuentra en la zona marcada en la tabla ilustra en la figura 2.
4.
1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1
0 1 2 3 4 5 6 7 8
s 0 0 0 0 1 0 1 0 2 1 0 2 1 0 2 1 2 0
n - Ls Ls
Tabla 4: Segunda iteración de compresión del segundo ejemplo

En ella se observa con claridad que, dado que Ls empieza


por 10, había una repetición en las posiciones 5 y 6, que
también son 10, que sin embargo no hemos marcado en
negrita dentro de la figura. Esto es debido a que la
secuencia formada por las posiciones 5 y 6, si bien
representa una repetición de lo que aparece en Ls, no se
trata de su extensión periódica ya que tiene longitud 2,
mientras que la coloreada en la figura tiene longitud 7. Figura 2:´Primera iteración de Descompresión del segundo ejemplo
Por ello S3=10210212 y C3=672.
La primera palabra que se lee es '021' (C1). El '0' sirve de
puntero en el buffer, y lo llamaremos "p''. Se debe leer el
5
carácter que está en la posición p+1, luego se lee el de la La siguiente palabra a decodificar es 672 (C3). Como
posición 1. Como inicialmente el buffer estaba puesto a antes, y esta vez por 7 veces, se guarda el carácter de la
0, no sorprende que lo que encontremos en la posición 1 posición 6+1 y se coloca a la derecha del buffer tras
sea un '0'. Tal y como está el buffer, se desplazan todos desplazarlo. El último carácter que se introduce por la
sus elementos una posición hacia la izquierda, y en el derecha nos viene dado en la palabra código: ahora es un
hueco que queda a la derecha se introduce el carácter '2'. La tercera iteración se ilustra en la figura 4.
leído con anterioridad en esa posición 1. El segundo
carácter de la palabra código es un '2'. Ello indica que la
operación anterior de leer y desplazar se debe hacer dos
veces, por lo que la repetimos: nuevamente se lee la
posición 1. Aunque la posición es la misma, el dato leído
no tiene por qué serlo, ya que el buffer se desplazó hacia
la izquierda. En este caso volvemos a tener un '0', y el
buffer tiene el mismo aspecto que antes. Al segundo
elemento de las palabras código lo llamaremos a partir de
ahora "n''. Puesto que ya hemos hecho dos veces la
operación, tantas como indicaba el n de la palabra código
que estamos decodificando, ahora se desplaza una vez
más a la izquierda, y en el hueco que ha aparecido se
introduce el tercer carácter de la palabra código (a partir
de ahora "c''), sin modificar: el '1'.
Al final de todas las figuras se resalta en negrita la parte
del buffer que corresponde a la descodificación de la
palabra código. Evidentemente, este tramo se encuentra
siempre al final del buffer, y su longitud es bien simple
de calcular: n+1.
La siguiente palabra a decodificar es 732 (C2). Como
antes, y esta vez por 3 veces, se guarda el carácter de la
posición 7+1 y se coloca a la derecha del buffer tras
desplazarlo. El último carácter que se introduce por la
derecha nos viene dado en la palabra código: ahora es un
'2'. La segunda iteración se ilustra en la figura 3.

Figura 4:´Tercera iteración de Descompresión del segundo ejemplo

Por último, la palabra a decodificar es 280 (C4). Como


antes, y esta vez por 8 veces, se guarda el carácter de la
posición 2+1 y se coloca a la derecha del buffer tras
desplazarlo. El último carácter que se introduce por la
derecha nos viene dado en la palabra código: ahora es un
'0'. La cuarta iteración se ilustra en la figura 5.

Figura 3:´Segunda iteración de Descompresión del segundo ejemplo


6
tomar las ocho posiciones últimas del buffer de esta
iteración, siendo la secuencia “10210212”.
Cuarta Iteración: C4=280, nos indica que hay ocho
posiciones repetidas adicionando la posición sin repetir
que para este caso es el número 0, por tanto, se debe tomar
las nueve posiciones últimas del buffer de esta iteración,
siendo la secuencia “021021200”.
Concatenando todas las secuencias resultantes en el orden
que han sido generadas en cada iteración nos da:
S=001 0102 10210212 021021200.
Que viene la cadena original, con lo que queda demostrado
mediante un ejemplo práctico la lógica de funcionamiento
del algoritmo LZ77.

3.2. Limitaciones

El método LZ77 ha sido mejorado desde su invención,


entre las mejoras destacan la utilización de campos O y L
de longitud variable y el uso de diferentes tamaños de
diccionario (longitud de la ventana).

Sin embargo, la utilización de una ventana más grande


implica mayor tiempo de búsqueda de los patrones y obliga
a la utilización de mejores estructuras de datos para realizar
la implementación. Por otra parte, el utilizar una ventana
más grande implica el uso de campos O y L más grandes
con lo que la razón de compresión se ve afectada.

Otro factor a considerarse es la posible expansión del


archivo en vez de la reducción deseada. Debido a que se
requiere un codeword de tres campos, esto puede producir
la expansión del archivo de salida para los casos donde la
Figura 5:´Cuarta iteración de Descompresión del segundo ejemplo subcadena encontrada sea de longitud 1 o 2. Una posible
solución es escribir al archivo de salida codewords cuando
Después de haber terminado de descomprimir todas las
la cadena encontrada sea de longitud mayor a 3 y escribir
iteraciones (C1,C2,C3.C4), ahora tenemos que
los símbolos sin comprimir cuando la cadena encontrada
concatenar los resultados obtenidos en cada iteración que
sea de longitud menor o igual a 3. Esto implica el uso de
han sido coloreados con gris.
un símbolo especial que permita diferenciar al
Primera Iteración: C1=021, nos indica que hay dos
decodificador entre codewords y datos no comprimidos.
posiciones repetidas adicionando la posición sin repetir
que para este caso es el número 1, por tanto, se debe 3.3. Variaciones del Algoritmo LZ77
tomar las tres posiciones últimas del buffer de esta
iteración, siendo la secuencia “001”. El algoritmo LZ77 mantiene su vigencia como
Segunda Iteración: C2=732, nos indica que hay tres consecuencia de su aplicación en distintas tareas que
posiciones repetidas adicionando la posición sin repetir requieren de la compresión de datos, así como fundamento
que para este caso es el número 2, por tanto, se debe de nuevas soluciones de compresión. Algunas de las
tomar las cuatro posiciones últimas del buffer de esta variaciones del algoritmo LZ77 son:
iteración, siendo la secuencia “0102”.
El algoritmo LZ78: (Lempel & Ziv, 1978) Es una
Tercera Iteración: C3=672, nos indica que hay siete
variación que no utiliza una ventana sobre los datos a
posiciones repetidas adicionando la posición sin repetir
comprimirse como en el caso del LZ77. Se tiene un
que para este caso es el número 2, por tanto, se debe
diccionario que contiene las cadenas que han ocurrido
7
previamente. El diccionario está vacío inicialmente y su 3.4. Implementación a través de un programa
tamaño está limitado por la memoria disponible. Para
ilustrar la forma en la que el método funciona, Para probar el algoritmo LZ77 se ha desarrollado un
considérese un diccionario (arreglo lineal) de N aplicativo en el lenguaje C# en donde se utiliza la
localidades con la capacidad de almacenar una cadena de programación orientada a objetos y los métodos que
símbolos en cada una de ellas. El diccionario se inicializa comprimen y descomprimen.
guardando en la posición cero del diccionario la cadena La interfaz desarrollada se muestra en la figura 6, donde se
vacía. El proceso es iterativo y termina cuando ya no solicita la cadena a comprimir y se muestra las tripletas
existen más símbolos a la entrada para codificar. (offset, longitud, carácter siguiente) generadas en cada
A diferencia del método LZ77, ahora los codewords se paso de la comprensión del algoritmo explicado.
componen solo de dos campos, un campo apuntador o
índice que identifica la posición de una cadena dentro del
diccionario y un campo que contiene el último símbolo
que se ha leído de la entrada. Entre más grande sea el
diccionario, más cadenas son almacenadas y se tienen
concordancias de cadenas más grandes que mejoran la
razón de compresión, pero se requieren apuntadores más
grandes y el tiempo de búsqueda se incrementa.

El algoritmo LZW (Welch, 1984): es una variante del


método LZ78. El codeword consiste ahora de únicamente
una referencia a la posición en el diccionario de la cadena
encontrada. En el caso de codificar símbolos de 8 bits, las
primeras 256 posiciones del diccionario se inicializan con Figura 6: Aplicativo para compresión con LZ77
los 256 símbolos antes de iniciar la codificación. Este
Se ha realizado la prueba con las cadenas mostradas en el
paso inicial asegura que cualquier símbolo leído de la
presente paper, la figura 7 muestra la compresión y
entrada siempre se localizará en el diccionario con lo que
descompresión de la cadena “00101011” para la prueba 01
es posible manejar únicamente un apuntador a la posición
del algoritmo de compresión LZ77.
del diccionario como código de salida. El codificador lee
cada símbolo de la entrada y los acumula en una cadena
S. Cada vez que un símbolo X es leído de la entrada, el
símbolo se concatena con S y la cadena resultante se
busca en el diccionario. Siempre que la concatenación es
encontrada en el diccionario, un nuevo símbolo X es leído
de la entrada, se concatena a S y se realiza la búsqueda de
la nueva cadena S∙X . Cuando la concatenación S∙X no se
encuentra en el diccionario (S se encuentra en el
diccionario pero S∙X no se encuentra), el codificador
escribe a la salida la posición en el diccionario de la
cadena S, guarda S∙X en una localidad disponible en el
diccionario e inicializa S con el símbolo X.

El diccionario en LZW puede implementarse, al igual que


en LZ78, por medio de un trie. Cada nueva cadena Figura 7: Prueba 01 del algoritmo LZ77
agregada al diccionario es diferente únicamente en un
La prueba 02 se ha hecho para verificar el segundo ejemplo
símbolo respecto a otra cadena ya existente (lo que en el
explicado en el presente paper donde la cadena a evaluar
trie sería una cadena padre). El problema con esta
fue: “001010210210212021021200”. Como puede
representación son las múltiples ramas que un nodo puede
observarse en la figura 8, la compresión es más eficiente
contener.
aun debido a que se encuentran subcadenas como “01” y
8
“02” repetidas muchas veces, por lo cual las tripletas van
indicando la forma en que se va comprimiendo.

Figura 9: clase clsDatos para almacenar la tripleta de busqueda

La clase clsAlgoritmoLZ77 es la encargada de registrar las


funciones de comprimir y descomprimir. La figura 10
muestra la clase y el método LZ77_Comprimir. Dentro del
método se hace el análisis explicado carácter a carácter
buscando la secuencia donde se empiezan a repetir, para
guardar como tripleta el carácter repetido o el inicio de una
subcadena repetida.

Figura 8: Prueba 02 del algoritmo LZ77

A continuación, se muestra el código de implementación


en C# de toda la clase que se ha programado para
codificar el algoritmo de compresión LZ77.

La figura 9 representa la clase de la tripleta (offset,


longitud, carácter siguiente) que nos servirá para ir
haciendo las “pasadas” de la compresión por el buffer de
almacenamiento.

Figura 10: Método para comprimir con LZ77

La figura 11, muestra el método LZ77 encargado de


descomprimir la tripleta generada en la “pasada” para
comprimir, donde el proceso concluye al encontrar la
palabra “eofk”.

9
- Las redes tienen como principal inconveniente la
velocidad de transferencia de grandes cantidades de
datos, y es este punto en donde la compresión sigue
teniendo su punto fuerte en temas de eficiencia en la
transmisión de datos.
- Teniendo en cuenta que existen algoritmos de
compresión con pérdida que omiten algo de
información y generan archivos más pequeños, el
algoritmo LZ77 es un algoritmo de compresión sin
pérdida, es decir que no omiten información al
momento de la compresión.
- El algoritmo LZ77 se utiliza cuando la información a
comprimir es importante y crítica y no es necesario
perder información y aun así es considerado un
algoritmo de compresión eficiente.
- El funcionamiento del algoritmo es simple, se
encarga de encontrar secuencias repetidas, pero al
incluir al final de la búsqueda el siguiente carácter del
buffer a comprimir que no forma parte de la secuencia
repetida, que talvez no tiene repetición por lo cual se
ahorra tiempo tratando de encontrar coincidencias.

Bibliografía

EcuRed. (Junio de 2017). Recuperado el Enero de 2019,


de Compresión de datos:
https://www.ecured.cu/Compresi%C3%B3n_de_d
atos
Kreft, S., & Navarro, G. (2017). Variante de LZ77 y
aplicaciones. Revista de la Universidad de Chile,
1-3.
Lempel, A., & Ziv, J. (1977). A Universal Algorithm for
Secuential Data Compression. IEEE Transactions
on Information Theory, 23, 337-343.
Lempel, A., & Ziv, J. (1978). Compression of Individual
Figura 11: Método para descomprimir con LZ77
Secuences via Variable‐Rate Coding. IEEE
Transactions on Information Theory, 24, 530-536.
Welch, T. (1984). A Technique for High‐Performance
4. Conclusiones Data Compression. IEEE Computer, 17, 8-19.
Wikipedia. (Diciembre de 2018). Recuperado el Enero de
- La compresión de dato actualmente podría
2019, de LZSS:
considerarse como un método no tan necesario,
https://es.wikipedia.org/wiki/LZSS
teniendo en cuenta las grandes capacidades de Witten, J., Moffat, A., & Bell, T. (1999). Managing
almacenamiento de datos de los dispositivos y Gigabytes: Compressing and Indexing Documents
también la velocidad de procesamientos de los and Images. Academic Press.
mismos. Sin embargo, aún sigue siendo necesarios
en los temas de intercambio de comunicación entre
dispositivos a distancia.

1
0
1
1

Das könnte Ihnen auch gefallen