|
O LZW (Lempel-Ziv-Welch) é um algoritmo de compressão de dados, derivado do algoritmo LZ78, baseado na localização e no registro das padronagens de uma estrutura. Foi desenvolvido e patenteado em 1984 por Terry Welch[1]. É geralmente utilizado em imagens em que não se pode perder a definição original. Nas imagens, o algoritmo lê os valores de pixels de uma imagem bitmap e elabora uma tabela de códigos onde se representam as padronagens repetidas dos pixels encontrados. O codificador LZW reduz, pela compressão, os arquivos de imagens gráficas a 1/3 ou 1/4 de seu tamanho original. Imagens com padronagem bem definidas — com grandes blocos de cor contínua ou repetidas de cores — podem reduzir para 1/10 o tamanho original do arquivo.
Formatos que utilizam a LZWAlgoritmoO algoritmo LZW é uma variante do LZ78 que visa eliminar a necessidade de se emitir um caractere literal junto com o endereço de dicionário[2]. Para isso, o dicionário é inicializado com todos os símbolos do alfabeto (ao se usar codificação ASCII são 256 símbolos, de 0 a 255). A entrada é lida e acumulada em uma cadeia de caracteres que chamaremos de I. Sempre que a seqüência contida em I não estiver presente no dicionário emitimos o código correspondente a versão anterior de I (ou seja, I sem o último caractere) e adicionamos I ao dicionário. I volta a ser inicializado com o último caractere lido (o seu último caractere) e o processo continua até que não hajam mais caracteres na entrada. Pseudo-Código
1. No início o dicionário contém todas as raízes possíveis e I é vazio;
2. c <= próximo caractere da sequência de entrada;
3. A string I+c existe no dicionário?
a. se sim,
i. I <= I+c;
b. se não,
i. coloque a palavra código correspondente a I na sequência codificada;
ii. adicione a string I+c ao dicionário;
iii. I <= c;
4. Existem mais caracteres na sequência de entrada ?
a. se sim,
i. volte ao passo 2;
b. se não,
ii. coloque a palavra código correspondente a I na sequência codificada;
iii. FIM.
Pseudo-Código descompactação String
1. No início o dicionário contém todas as raízes possíveis;
2. cW <= primeira palavra código na sequência codificada (sempre é uma raiz);
3. Coloque a string(cW) na sequência de saída;
4. pW <= cW;
5. cW <= próxima palavra código da sequência codificada;
6. A string(cW) existe no dicionário ?
a. se sim,
i. coloque a string(cW) na sequência de saída;
ii. P <= string(pW);
iii. C <= primeiro caracter da string(cW);
iv. adicione a string P+C ao dicionário;
b. se não,
i. P <= string(pW);
ii. C <= primeiro caracter da string(pW);
iii. coloque a string P+C na sequência de saída e adicione-a ao dicionário;
7. Existem mais palavras código na sequência codificada ?
a. se sim,
i. volte ao passo 4;
b. se não,
i. FIM.
ExemploNo quadro abaixo mostramos os passes da compressão da cadeia
O tamanho final é de 10 códigos, que podem ser representados por 9 bits cada um. Nesse caso temos na saída 90 bits, comparados com os 104 originais. Como podemos ver, o método LZW é ainda mais lento para fazer efeito que o método LZ78 devido ao fato de o dicionário já estar inicialmente povoado com todos os símbolos do alfabeto. Entretanto ele é mais simples de ser implementado e gera resultados semelhantes ou até melhores com cadeias de caracteres mais longas. ProblemasPor ser uma variante do LZ78 o LZW sofre dos mesmos problemas enfrentados por este, que podem ser vistos em LZ78#Problemas. Exemplo de implementação#!/usr/bin/python # coding: utf-8 import sys class lzw_encoder: """ Classe usada para codificar um arquivo usando o algorítmo LZW. Está é uma implementação de exemplo que não leva em conta a representação binária do arquivo de saída nem o estouro do tamanho do dicionário. Este código foi baseado nas informações contidas em http://pt.wikipedia.org/wiki/LZW """ def __init__(self): """ Faz a carga inicial do dicionário com os 256 caracteres ASCII possíveis. """ 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 código para uma dada "string" e a insere sob esse código no dicionário """ self.dictionary[str] = self.next_code self.next_code = self.next_code + 1 def encode(self, str): """ Corpo do algorítmo. lê sequencialmente os caracteres e cria as cadeias a serem inseridas no dicionário, emitindo os respectivos códigos no arquivo de saída (representado pela lista "ret" """ ret = [] # inicializa a lista (arquivo de saída) buffer = '' # inicializa o acumulador de caracteres lidos for i in range(0, len(str)): c = str[i] # enquanto a cadeia atual existir no dicionário, # continuamos acresncentando caracteres a ela if len(buffer) == 0 or self.dictionary.has_key(buffer + c): buffer = buffer + c else: # quando encontramos a mairo cadeia presente # emitimos o código 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 restrições da classe lzw_encoder """ def __init__(self): """ Faz a carga inicial do dicionário com os 256 caracteres ASCII possíveis. """ 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 código para uma dada "string" e a insere sob esse código no dicionário """ self.dictionary[self.next_code] = str self.next_code = self.next_code + 1 def decode(self, symbols): """ Decodifica o arquivo. Emite sequêncialmente as cadeias correspondentes aos códigos lidos. Caso a concatenação dos códigos lidos não corresponda a uma cadeia existente, acrescenta no dicionário 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) Notas e referências
Bibliografia
Ligações externas
|
This article is from Wikipedia. All text is available under the terms of the GNU Free Documentation License.
Mercedes Car
This site monitored by SitePinger.net