Você está na página 1de 8

Lempel-Ziv

Ana Carolina Clivatti Ferronato Programao com Arquivo

Introduo
O LZW (Lempel-Ziv-Welch) um algoritmo de compresso de dados, derivado do algoritmo LZ78, baseado na localizao e no registro das padronagens de uma estrutura. Foi desenvolvido e patenteado em 1984 por Terry Welch[1]. geralmente utilizado em imagens em que no se pode perder a definio original. Nas imagens, o algoritmo l os valores de pixels de uma imagem bitmap e elabora uma tabela de cdigos onde se representam as padronagens repetidas dos pixels encontrados. O codificador LZW reduz, pela compresso, os arquivos de imagens grficas a 1/3 ou 1/4 de seu tamanho original. Imagens com padronagem bem definidas com grandes blocos de cor contnua ou repetidas de cores podem reduzir para 1/10 o tamanho original do arquivo.

Algoritmo LZ77
Este algoritmo baseado em duas janelas contguas de tamanho xo: a primeira geralmente denominada de dicionrio e a segunda de lookahead bufferou simplesmente de buffer. A posio das janelas vai sendo deslocada medida que os smbolos vo sendo codicados. Um dicionrio de comprimento Nd uma janela que contm os ltimos Nd smbolos codicados. Um buffer de comprimento Nb uma janela que contm os prximos Nb a codicar. O cursor um apontador para o prximo smbolo a codicar (primeira posio do lookahead buffer). O algoritmo LZ77 divide a sequncia de smbolos a codicar num conjunto de sub-sequncias, e associa a cada subsequncia um cdigo composto por 2 inteiros e um smbolo (caractere). Este processo descrito de seguinda.

Formatos que Aceitam LZW


TIFF, por opo; GIF, por padro.

Algoritmo
O algoritmo LZW uma variante do LZ78 que visa eliminar a necessidade de se emitir um caractere literal junto com o endereo de dicionrio. Para isso, o dicionrio inicializado com todos os smbolos do alfabeto (ao se usar codificao ASCII so 256 smbolos, de 0 a 255). A entrada lida e acumulada em uma cadeia de caracteres que chamaremos de I. Sempre que a seqncia contida em I no estiver presente no dicionrio emitimos o cdigo correspondente a verso anterior de I (ou seja, I sem o ltimo caractere) e adicionamos I ao dicionrio. I volta a ser inicializado com o ltimo caractere lido (o seu ltimo caractere) e o processo continua at que no haja mais caracteres na entrada.

Pseudo-Cdigo
1. No incio o dicionrio contm todas as razes possveis e I vazio; 2. c <= prximo caractere da sequncia de entrada; 3. A string I+c existe no dicionrio? a. se sim, i. I <= I+c; b. se no,

i. coloque a palavra cdigo correspondente a I na sequncia codificada; ii. adicione a string I+c ao dicionrio; iii. I <= c; 4. Existem mais caracteres na sequncia de entrada ? a. se sim, i. volte ao passo 2; b. se no, ii. coloque a palavra cdigo correspondente a I na sequncia codificada; iii. FIM.

Pseudo-Cdigo descompactao String


1. No incio o dicionrio contm todas as razes possveis; 2. cW <= primeira palavra cdigo na sequncia codificada (sempre uma raiz); 3. Coloque a string(cW) na sequncia de sada; 4. pW <= cW; 5. cW <= prxima palavra cdigo da sequncia codificada; 6. A string(cW) existe no dicionrio ? a. se sim, i. coloque a string(cW) na sequncia de sada; ii. P <= string(pW); iii. C <= primeiro caracter da string(cW); iv. adicione a string P+C ao dicionrio; b. se no, i. P <= string(pW); ii. C <= primeiro caracter da string(pW); iii. coloque a string P+C na sequncia de sada e adicione-a ao dicionrio; 7. Existem mais palavras cdigo na sequncia codificada ? a. se sim, i. volte ao passo 4; b. se no, i. FIM.

Exemplo
No quadro abaixo se mostra os passes da compresso da cadeia A_ASA_DA_CASA usando o mtodo de LZW. A coluna I representa a cadeia lida na entrada desde que a ltima sada foi emitida. A coluna no dic Indica se a seqncia em I est presente no dicionrio. a coluna nova

entrada mostra o que ser inserido no dicionrio (como o dicionrio j contm os 256 smbolos do cdigo ASCII impraticvel mostrar todo seu contedo, por isso listamos apenas as novas entradas). E por fim a coluna sada mostra o cdigo que ser emitido na sada do programa, junto com o que ele representa no dicionrio (entre parnteses).
I A A_ _ _A A AS S SA A A_ A_D D DA A A_ A_C C CA A AS ASA no dic? nova entrada sada S N S N S N S N S S N S N S S N S N S S N 264:ASA 258 (AS) 263:CA 67 (C) 262:A_C 256 (A_) 261:DA 68 (D) 260:A_D 256 (A_) 259:SA 83 (S) 258:AS 65 (A) 257:_A 95 (_) 256:A_ 65 (A)

A -

S 65 (A)

O tamanho final de 10 cdigos,sendo 7 representados por 8 bits cada um e 3 cdigo representados por 9 bits. Nesse caso temos na sada 83 bits, comparados com os 104 originais. Como podemos ver, o mtodo LZW ainda mais lento para fazer efeito que o mtodo LZ78 devido ao fato de o dicionrio j estar inicialmente povoado com todos os smbolos do alfabeto. Entretanto ele mais simples de ser implementado e gera resultados semelhantes ou at melhores com cadeias de caracteres mais longas.

Problemas
Por ser uma variante do LZ78 o LZW sofre dos mesmos problemas enfrentados por este, que podem ser vistos em LZ78#Problemas. Exemplo de implementao **
#!/usr/bin/python # coding: utf-8 import sys class lzw_encoder: """ Classe usada para codificar um arquivo usando o algoritmo LZW. Est uma implementao de exemplo que no leva em conta a representao binria do arquivo de sada nem o estouro do tamanho do dicionrio. Este cdigo foi baseado nas informaes contidas em http://pt.wikipedia.org/wiki/LZW """ def __init__(self): """ Faz a carga inicial do dicionrio com os 256 caracteres ASCII possveis. """ self.next_code = 0 self.dictionary = dict() for i in range(0,256): self.add_to_dictionary(chr(i)) def add_to_dictionary(self, str): """ Cria um novo cdigo para uma dada "string" e a insere sob esse cdigo no dicionrio """

self.dictionary[str] = self.next_code self.next_code = self.next_code + 1 def encode(self, str): """ Corpo do algoritmo. l sequencialmente os caracteres e cria as cadeias a serem inseridas no dicionrio, emitindo os respectivos cdigos no arquivo de sada (representado pela lista "ret" """ ret = [] # inicializa a lista (arquivo de sada) buffer = '' # inicializa o acumulador de caracteres lidos for i in range(0, len(str)): c = str[i] # enquanto a cadeia atual existir no dicionrio, # continuamos acresncentando caracteres a ela if len(buffer) == 0 or self.dictionary.has_key(buffer + c): buffer = buffer + c else: # quando encontramos a maior cadeia presente # emitimos o cdigo dessa cadeia e criamos uma # nova cadeia, acrescentando o ltimo # caractere lido. code = self.dictionary[buffer] self.add_to_dictionary(buffer + c) buffer = c ret = ret + [code] if buffer: ret = ret + [self.dictionary[buffer]] return ret class lzw_decoder: """ Classe usada para decodificar um arquivo codificado com LZW. Segue as mesmas restries da classe lzw_encoder """ def __init__(self): """ Faz a carga inicial do dicionrio com os 256 caracteres ASCII possveis. """ self.next_code = 0 self.dictionary = dict() for i in range(0,256): self.add_to_dictionary(chr(i)) def add_to_dictionary(self, str): """

Cria um novo cdigo para uma dada "string" e a insere sob esse cdigo no dicionrio """ self.dictionary[self.next_code] = str self.next_code = self.next_code + 1 def decode(self, symbols): """ Decodifica o arquivo. Emite sequncialmente as cadeias correspondentes aos cdigos lidos. Caso a concatenao dos cdigos lidos no corresponda a uma cadeia existente, acrescenta no dicionrio como uma nova cadeia. """ last_symbol = symbols[0] ret = self.dictionary[last_symbol] for symbol in symbols[1:]: if self.dictionary.has_key(symbol): current = self.dictionary[symbol] previous = self.dictionary[last_symbol] to_add = current[0] self.add_to_dictionary(previous + to_add) ret = ret + current else: previous = self.dictionary[last_symbol] to_add = previous[0] self.add_to_dictionary(previous + to_add) ret = ret + previous + to_add last_symbol = symbol return ret if __name__ == "__main__": str = '' str = 'A_ASA_DA_CASA' encoder = lzw_encoder() encoded = encoder.encode(str) print ('encoded:', encoded) decoder = lzw_decoder() decoded = decoder.decode(encoded) print ('decoded:', decoded)

Você também pode gostar