Escolar Documentos
Profissional Documentos
Cultura Documentos
(Compressão)
Estrutura de Dados II
Jairo Francisco de Souza
Compressão de Dados
• Objetivos
– Reduzir espaço de armazenagem
– Reduzir tempo de transmissão
• Muito importante
– Informação (e dados) tende a crescer de forma exponencial
• Exemplos:
– Compressão de arquivos em geral
• ZIP, GZIP, BZIP, BOA.
– Sistemas de arquivos: NTFS.
– Multimídia
• Imagens: GIF, JPEG
• Som: MP3.
• Vídeo: MPEG, DivX™, HDTV.
– Comunicação
• Modems
• Faxes
Compressão x Compactação
• Compressão
– Mudança na representação de algum dado
para reduzir seu tamanho
• Compactação
– União de dados que não estão unidos
• Exemplo:
– Compressão do HD: reduzir o tamanho dos
arquivos
– Compactação do HD: juntar partes disjuntas
(desfragmentar)
Sistemas de recuperação de
informação
• Métodos recentes de compressão têm
permitido:
– 1. Pesquisar diretamente o texto comprimido
mais rapidamente do que o texto original.
– 2. Obter maior compressão em relação a
métodos tradicionais, gerando maior
economia de espaço.
– 3. Acessar diretamente qualquer parte do
texto comprimido sem necessidade de
descomprimir todo o texto desde o início
Codificação e Decodificação
• Seja M a mensagem que desejamos
armazenar/transmitir
– Codificação: Gerar uma representação “comprimida” C(M) que,
espera-se, utilize menos bits
– Decodificação: Reconstrução da mensagem original ou alguma
aproximação M’
• Razão de Compressão: bits de C(M) / bits de M
• Compressão sem perda: M = M’
– Texto, programas fonte, executáveis etc
– RC: 50-75% ou menos
• Compressão com perda: M ~ M’
– Imagens, som, vídeo
– Uma idéia é descartar informação não perceptível pelos
sentidos
– RC: 10% ou mais, dependendo do fator de qualidade
Compressão - curiosidade
• KGB Archiver
– Programa para compressão sem perda
– "Comprima 700mb em 1mb!"
• Arquivos textos: Razão de compressão de menos de
10%
• Aplicativos: razão de compressão de menos de 25%
– PAQ
• Série de algoritmos criados colaborativamente.
– Dependente da memória RAM disponibilizada e
extremamente lento.
• Geralmente precisando de algumas horas, mas
podendo chegar a dias, semanas...
Codificação por Seqüências
Repetidas
• Conhecida como Run-length encoding (RLE).
• Idéia é explorar longas seqüências de caracteres repetidos
– Substituir seqüência pelo número de repetições seguido do caractere repetido
– Se seqüência tem menos de 3 caracteres, ignorar regra
• Exemplo:
– AAAABBBAABBBBBCCCCCCCCDABCBAAABBBBCCCD
4A3BAA5B8CDABCB3A4B3CD
• Como representar o número de repetições?
– Alguns esquemas + ou – complicados
– Pode levar à inflação de um arquivo se as seqüências são curtas
• Se o arquivo é binário, saída consiste apenas de contagens de repetições
– Por exemplo, tente comprimir a cadeia 10001110011111001101
• Aplicações
– Imagens preto e branco
– Usado nos arquivos .rle do Windows 3.x, que eram bitmaps usadas na tela de
inicialização do sistema operacional.
– Impressoras térmicas (impressoras em aeroportos para impressão de bilhetes, etc).
Codificação de Huffman
• Idéia é usar caracteres (símbolos) com número variável
de bits
– Caracteres mais comuns na mensagem são codificados com
menos bits e caracteres menos comuns com mais
• Árvore de Prefixos de Huffman
– Dada uma mensagem, encontra a melhor (menor) codificação
para os caracteres
– Algoritmo:
• Tabular freqüências dos símbolos
• Montar uma floresta de tries unitários com todos os
símbolos e suas freqüências
• Repetir
– Localizar os dois tries com menor freqüência Fi e Fj
– Uní-los num trie único com freqüência Fi + Fj
Exemplo de Codificação de
Huffman Char Freq
E 125
• Freqüências dos T 93
A 80
caracteres O 76
I 72
N 71
• Árvore de Huffman S 65
é um heap R 61
– Pode implementar H 55
utilizando um array, L 41
assim como é feito no D 40
HeapSort C 31
U 27
Exemplo de Codificação de
Huffman
A O T E
80 76 93 125
D L R S N I H
40 41 61 65 71 73 55
C U
31 27
Exemplo de Codificação de
Huffman
A O T E
80 76 93 125
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
A O T E
80 76 81 93 125
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
A O T E
80 76 81 93 125 113
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
A O T E
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
A O T E
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
156
A O T E
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
156 174
A O T E
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
156 174
238
A O T E
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
330
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
330 508
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
Huffman
838
330 508
D L R S N I H
40 41 61 65 71 73 58 55
C U
31 27
Exemplo de Codificação de
HuffmanChar Freq Fixo Huff
E 125 0000 110
T 93 0001 011
A 80 0010 000
O 76 0011 001
I 73 0100 1011
N 71 0101 1010
S 65 0110 1001
R 61 0111 1000
H 55 1000 1111
L 41 1001 0101
D 40 1010 0100
C 31 1011 11100
U 27 1100 11101
Total 838 4.00 3.62
Codificação de Huffman
• Implementação.
– Dois passos
• Tabular freqüências e construir o trie
• Codificar mensagem percorrendo o trie
– Usar uma fila de prioridades (heap)
• Complexidade O(M + N log N)
– M é o comprimento da mensagem
– N é o número de caracteres distintos
• Dificuldades
– Transmissão do trie
• Pode ser resolvido com variante progressiva (Knuth): Trie é
construído simultaneamente pelo codificador e decodificador
Codificação de Huffman
• Em algumas aplicações, como sistemas
de recuperação de informação, o uso de
palavras ao invés de caracteres torna-se
importante
• Métodos de Huffman baseados em
caracteres comprimem o texto para
aproximadamente 60%.
• Métodos de Huffman baseados em
palavras comprimem o texto para valores
pouco acima de 25%.
Codificação de Huffman
• Exemplo:
– “Para cada rosa rosa, uma rosa é uma rosa”
• Divisão do texto:
– Separadores são caracteres que aparecem entre palavras:
espaço, vírgula, ponto, ponto e vírgula, interrogação, e assim
por diante.
– Uma forma eficiente de lidar com palavras e separadores é
representar o espaço simples de forma implícita no texto
comprimido.
– Nesse modelo, se uma palavra é seguida de um espaço, então,
somente a palavra é codificada.
– Senão, a palavra e o separador são codificados separadamente.
– No momento da decodificação, supõe-se que um espaço
simples segue cada palavra, a não ser que o próximo símbolo
corresponda a um separador.
Exercício
• Codifique o texto abaixo usando a
codificação de Huffman
– yabba dabba doo
0 1c
0 2c 0 1f
Exemplo (aplicando o algoritmo)
• Repare que o incremento da frequência é
feito tardiamente...
4
4 4
2 2a p
2 2a 2 2a
+c p ← ascendente de p
1 1f
1 1f 1 2c
p
0 1c p
0 2c 0 1f incrementa p
p
5 4 4
p ← ascendente de p p p
2a 3 2a 3 swap 3 2a
2c incrementa p 2c 2c
1 1 1
0 1f 0 1f 0 1f
Huffman adaptativo
Código gerado para “ABRACADABRA”:
“A 0 B 00 R 0 100 C 0 1100 D 0 110 110 0”
40
Algoritmo LZ77
• Baseado em duas janelas contíguas de
tamanho fixo: dicionário e buffer
• A posição das janelas vão sendo
deslocadas à medidas que os símbolos
vão sendo codificados.
41
Algoritmo LZ77: Codificador
• Inicializa-se o buffer (de dimensão Nb) com os primeiros
Nb símbolos da sequência a codificar
• Inicialmente o dicionário não contém nenhum símbolo
• Enquanto houver símbolos a codificar
– Identificar no dicionário a maior sequência de símbolos
que também esteja presente no buffer (a começar no
cursor)
– Associar à sequência o código (p, l, c) onde
• p é a posição relativa (a contar do cursor) da maior sequência do
dicionário
• l é o comprimento da maior sequência
• c é o símbolo do buffer que se segue à sequência
– Deslocar as janelas (dicionário + buffer) de l+1 símbolos
42
Questões de implementação
• Caso 1
– Quanto não existe nenhuma sequência no
dicionário que corresponda às sequências do
buffer (a começar do cursor), então o código
para esses casos é (0, 0, c), onde c é o
primeiro símbolo do buffer
43
Questões de implementação
• Caso 2
– É vantajoso poder codificar certas sequências com p
< l. Por exemplo, considere a seguinte situação
47
Exercício
• Codifique a seguinte cadeia com LZ77,
considerando buffer de tamanho 4 e
dicionário de tamanho 6
– ATGTCGTCATGTCATGCTAGCTATGTGTCA
TGTATG
49
Algoritmo LZ78 - Codificador
• Dicionário = null
• String = null
• Enquanto houver símbolos para codificar
– c = próximo símbolo
– Se String+c é uma sequência presente no
dicionário
• String = String + c
– Caso contrário
• Enviar código (índice de String no Dicionário, c)
• Atualizar Dicionário com String + c
50
• String = null
Exemplo - LZ78
• Sequência a codificar: bananabanabofana
51
52
LZ78 - Decodificador
• Exemplo:
(0, p), (0, a), (1, a), (0, i), (2, p), (2, i), (2, b), (0, o), (0, f), (6, a)
53
LZ78 - Decodificador
• Exemplo:
(0, p), (0, a), (1, a), (0, i), (2, p), (2, i), (2, b), (0, o), (0, f), (6, a)
54
Exercício
• Codifique a seguinte cadeia com LZ78
– ATGTCGTCATGTCATGCTAGCTATGTGTCA
TGTATG
55
Algoritmo LZW
• Modificação do LZ78 desenvolvido e patenteado por
Terry Welch em 1984
• É geralmente utilizado em imagens nas quais não
se quer perder a definição original.
• O codificador LZW reduz, pela compressão, os
arquivos de imagens gráficas a 1/3 ou 1/4 de seu
tamanho original.
• Usado nos formatos TIFF (opcional) e GIF (padrão)
• O algoritmo exclui o símbolo da palavra de código
56
Algoritmo LZW - Codificador
• Dicionário = todos os símbolos da fonte (por
exemplo, a tabela ASCII)
• String = 1o símbolo da sequência a codificar
• Enquanto houver símbolos para codificar
– c = próximo símbolo
– Se String+c é uma sequência presente no Dicionário
• String = String + c
– Caso contrário
• Enviar código (índice de String no Dicionário)
• Atualizar Dicionário com String+c
• String = c
– Enviar código (índice de String no Dicionário)
57
Exemplo - ZVW
• Sequência a codificar: bananabanabofana
• Dicionário inicializado com a tabela ASCII
estendida (de 0 a 255)
• String inicializada com o 1o caracter da
sequência
58
59
Algoritmo LZW - Decodificador
• Dicionário = todos os símbolos da fonte (por exemplo, a
tabela ASCII)
• Stringold = 1o símbolo da sequência a codificar
• Saída = Stringold
• Enquanto houver códigos para decodificar
– Lê novo código
– Stringnew = sequência correspondente a novo código
– Saída = Stringnew
– c = 1o símbolo de Stringnew
– Adicionar Stringold + c a Dicionário
60
– Stringold = Stringnew
Algoritmo LZW - Decodificador
• Exemplo:
(112), (97), (256), (105), (257), (97), (259), (98), (111), (102), (261), (97)
Dicionário inicializado com a tabela ASCII
61
Exercício
• Codifique a seguinte string com LZW
– ATGTCGTCATGTCATGCTAGCTATGTGTCA
TGTATG
62