repositorio.unicamp.brrepositorio.unicamp.br/jspui/bitstream/REPOSIP/260325/1/Abushaala... ·...
Transcript of repositorio.unicamp.brrepositorio.unicamp.br/jspui/bitstream/REPOSIP/260325/1/Abushaala... ·...
UNIVERSIDADE ESTADUAL DE CAMPINAS FACULDADE DE ENGENHARIA ELÉTRICA E DE COMPUTAÇÃO
DEPARTAMENTO DE COMUNICAÇÕES
CODIFICAÇÃO PROGRESSIVA SEM PERDAS UTILIZANDO A TÉCNICA DE CODIFICAÇÃO ARITMÉTICA BASEADA NO PADRÃO JBIG
Autor Ahmed Mohamed Abushaala
Orientador Prof. Dr. Yuzo Iano
Banca Examinadora:
Prof. Evaldo Gonçalves Pelaes (UFPA)
Prof. Antônio Cláudio Paschoarelli Veiga (UFU)
Prof. Dr. José Antônio Siqueira Dias (FEEC/UNICAMP)
Prof. Dr. João Baptista Tadanobu Yabu-uti (FEEC/UNICAMP)
Prof. Dr. Edson Moschim (FEEC/UNICAMP)
Tese apresentada à Faculdade de Engenharia Elétrica e de Computação da Universidade Estadual
de Campinas como parte dos requisitos para a obtenção do título de Doutor em Engenharia
Elétrica.
Campinas, Abril de 2004
ii
iii
RESUMO Neste trabalho, apresenta-se um tutorial sobre a técnica de Codificação Aritmética
Binária Adaptativa (CABA), onde a CABA é a base principal do padrão JBIG (“Joint Bi-level
Image Experts Group”). O esforço é dedicado para o estudo e a implementação de quatro sub-
blocos que fazem parte do padrão JBIG: sub-bloco “Redutor de Resolução”, sub-bloco
“Predição Típica”, sub-bloco “Template Modelo” e sub-bloco “Codificador Aritmético
Adaptativo”. O presente trabalho tem como objetivo o desenvolvimento de protótipo software de
“Codec” de CABA para imagens de escala de cinzas e imagens coloridas, tendo-se em vista a
codificação sem perdas. Realizou-se a simulação de uma nova proposta usando-se método
progressivo do padrão JBIG com o objetivo de se representar a informação de imagem em
planos de bits e camadas de resolução. Essa proposta consiste em se transferir o modo
progressivo para o decodificador do JBIG ao invés de usá-lo no codificador que é o
procedimento comum. Isso permitirá o ganho desejado na taxa de compressão. Os resultados
numéricos são apresentados e analisados.
ABSTRACT In this work, a tutorial about an Adaptive Binary Arithmetic Coding technique (ABAC) is
presented, where the ABAC is the principal base of the JBIG standard (“Joint Bi-level Image
Experts Group”). The main effort is dedicated to the study and the implementation of four sub-
blocks of the JBIG standard namely: sub-block “Resolution Reduction”, sub-block “Typical
Prediction”, sub-block “Model Template” and sub-block “Adaptive Arithmetic Encoder”. The
main objective of this work is the development of a software prototype of Codec of ABAC for
greyscale and colour images, with the aim to obtain a lossless coding. The simulation of a new
proposal was realised using the progressive method of the JBIG standard with the objective of
representing the image information in bit-planes and resolution layers. This proposal consists of
transferring the progressive mode to the decoder of JBIG instead of using the common
procedure. This would allow the desired gain in the compression ratio. The numerical results are
presented and analysed.
iv
v
Dedico este trabalho à minha querida esposa Fatema,
aos meus filhos (Sarah e Mohamed)
e aos meus pais e meus irmãos.
vi
vii
O Profeta Mohammad (mensageiro de Deus), que a paz esteja com ele,
disse:
“Àquele que persegue a senda do conhecimento,
Deus dirigirá para a senda do paraíso”.
viii
ix
AGRADECIMENTOS
• Em primeiro lugar a Deus por tudo e sobre tudo;
• À minha querida esposa por tudo;
• Aos meus pais e aos meus irmãos, pelo apoio, incentivo e inúmeras contribuições;
• Ao Prof. Dr. Yuzo Iano, pela amizade, apoio e orientação;
• Aos colegas do curso de Mestrado e de Doutorado pela amizade;
• A todos os amigos do Departamento de Comunicações (DECOM), professores, alunos e
funcionários;
• Às pessoas que, de alguma maneira, contribuíram para a realização deste trabalho;
• Por fim, gostaria de expressar minha profunda gratidão ao Ministério da Educação do governo
da Líbia, ao Higher Polytechnical Institute (Misurata-Libya), à Coordenação de
Aperfeiçoamento de Pessoal de Nível Superior (CAPES), ao Fundo de Apoio ao Ensino e à
Pesquisa (FAEP/UNICAMP), à Fundação de Amparo a Pesquisa do Estado de São Paulo
(FAPESP), ao Centro de Pesquisa e Desenvolvimento da Telebrás (CPqD/Telebrás), ao
Conselho Nacional de Desenvolvimento Científico e Tecnológico (CNPq), e ao Governo
Brasileiro, pelo apoio financeiro e oportunidade oferecidas, que permitiram a concretização
deste trabalho.
x
xi
CONTEÚDO
CAPÍTULO 1: Conceitos Gerais 1.1 Introdução .................................................................................................... 1
1.2 A Compressão e suas Aplicações em Telecomunicações ..................... 3
1.3 A Técnica de Codificação Sem Perdas ..................................................... 5
CAPÍTULO 2: O Padrão JBIG 2.1 Introdução .................................................................................................... 9
2.2 O Modo Progressivo .................................................................................. 10
2.2.1 Estrutura Geral ................................................................................ 11
2.3 As Vantagens da Técnica de Codificação do JBIG ................................ 16
2.4 Blocos de Codificação do JBIG ............................................................... 17
2.4.1 Sub-blocos de Codificador de Camada Diferencial e Redutor
De Resolução e de Camada de Menor Resolução ...................... 18
2.5 Blocos de Decodificação do JBIG ........................................................... 24
2.6 Nova Proposta Para a Codificação Progressiva do JBIG .................... 26
CAPÍTULO 3: A Estrutura do Template Modelo 3.1 Introdução ................................................................................................. 31
3.2 O Modelo ................................................................................................... 32
xii
3.3 A Estrutura do Modelo Usado ................................................................. 33
3.4 O Cálculo do Contexto ............................................................................. 35
3.5 Comentários .............................................................................................. 36
CAPÍTULO 4: Codificação e Decodificação Aritmética 4.1 Introdução .................................................................................................. 39
4.2 A História da Codificação Aritmética ...................................................... 40
4.3 A Codificação Aritmética Binária Adaptativa (CABA) ........................... 41
4.4 O Mecanismo do Processamento do CAA ............................................. 42
4.4.1 O Processo de Codificação ........................................................... 44
4.5 A Decodificação Aritmética Binária Adaptativa (DABA) ....................... 47
4.6 A Codificação Aritmética Não Binária .................................................... 48
4.7 Comentários .............................................................................................. 54
CAPÍTULO 5: As Rotinas De Implementação 5.1 Introdução .................................................................................................. 57
5.2 O Procedimento de CABA ........................................................................ 60
5.2.1 Determinação dos Intervalos ........................................................ 60
5.2.2 Rotinas e Fluxogramas de Codificação ....................................... 62
5.3 O Procedimento de DABA ....................................................................... 73
5.3.1 Rotinas e Fluxogramas de Decodificação ................................... 74
5.4 Comentários .............................................................................................. 82
xiii
CAPÍTULO 6: Simulações e Resultados 6.1 Introdução ................................................................................................. 85
6.2 Imagens Fonte .......................................................................................... 86
6.3 Formato das Imagens Fonte .................................................................... 90
6.4 Organização dos Dados Processados ................................................... 94
6.4.1 Decomposição da Imagem Processada JBIG ............................. 94
6.4.2 A Ordem da Leitura dos Dados de Entrada ............................... 99
6.5 Avaliação do Algoritmo de Codificação Progressiva ......................... 100
6.5.1 Os Resultados das Imagens com Escala de Cinzas ................ 100
6.5.2 Os Resultados das Imagens Coloridas ..................................... 109
CAPÍTULO 7: Conclusões e Sugestões 7.1 Conclusões ............................................................................................. 115
7.2 Contribuições ......................................................................................... 117
7.3 Sugestões ............................................................................................... 120
APÊNDICES ............................................................................................ 121 REFERÊNCIAS BIBLIOGRÁFICAS ...................................... 187 TRABALHOS PUBLICADOS ..................................................... 191
xiv
xv
LISTA DE FIGURAS
2.1- Decomposição fornecida pela codificação progressiva de: 1 plano
de bits, 3 tiras e 3 camadas de resolução .................................................... 12
2.2- Decomposição fornecida pela codificação progressiva de: 2 planos
de bits, 3 tiras e 3 camadas de resolução ................................................... 12
2.3- Blocos do codificador ................................................................................... 17
2.4- Codificador de camada diferencial e redutor de resolução ...................... 19
2.5- Codificador de camada de menor resolução ...............................................19
2.6- Os pixels usados para se determinar o valor do pixel na camada
de baixa resolução ........................................................................................ 22
2.7- Blocos do decodificador ............................................................................... 25
2.8- Decodificador de camada diferencial .......................................................... 25
2.9- Decodificador de camada de menor resolução .......................................... 26
2.10- Bloco do codificador da nova proposta ...................................................... 28
2.11- Sub-blocos do codificador de planos de bits ............................................. 28
2.12- Bloco do decodificador da nova proposta .................................................. 28
2.13- Sub-blocos do decodificador de planos de bits ......................................... 29
3.1- Template modelo de Markov de duas linhas ............................................... 33
3.2- Template modelo de Markov de três linhas ................................................ 34
3.3- Template modelo de Markov para as 4 fases ............................................. 35
4.1- Entradas e saída do sub-bloco CAA ........................................................... 42
xvi
4.2- Subdivisão do intervalo ................................................................................ 43
4.3- Operação de subdivisão dos intervalos ...................................................... 45
4.4- Entradas e saída do sub-bloco DAA ............................................................ 47
4.5- Distribuição das palavras código no intervalo IC ....................................... 49
4.6- Subdivisão do intervalo para codificar a seqüência �a a d� ..................... 50
5.1- Fluxograma do codificador CAA .................................................................. 63
5.2- Fluxograma da rotina INITC .......................................................................... 64
5.3- Fluxograma da rotina CODIF ........................................................................ 65
5.4- Fluxograma da rotina MPSCOD .................................................................... 66
5.5- Fluxograma da rotina LPSCOD ..................................................................... 68
5.6- Fluxograma da rotina RENORMCOD ............................................................ 69
5.7- Fluxograma da rotina BYTEOUT ................................................................... 71
5.8- Fluxograma da rotina FIMC ........................................................................... 71
5.9- Fluxograma da rotina ZERARBITS ............................................................... 72
5.10- Fluxograma da rotina ESCREVFIM ............................................................... 73
5.11- Fluxograma do decodificador DAA .............................................................. 74
5.12- Fluxograma da rotina INITD .......................................................................... 76
5.13- Fluxograma da rotina LERBYTE ................................................................... 77
5.14- Fluxograma da rotina DECODIF ................................................................... 78
5.15- Fluxograma da rotina MPSDECOD ............................................................... 79
5.16- Fluxograma da rotina LPSDECOD ................................................................ 80
5.17- Fluxograma da rotina RENORMDEC ............................................................ 82
6.1- Imagens com escala de cinzas ..................................................................... 88
6.2- Imagens coloridas ..........................................................................................90
xvii
6.3- A estrutura da imagem com escala de cinzas de formato PGM ................ 92
6.4- Imagem de 36x6 pixels de palavra JBIG ...................................................... 93
6.5- A representação da imagem JBIG na memória .......................................... 93
6.6- As imagens recuperadas quando D = 3 ..................................................... 106
6.7- As imagens recuperadas de camadas de menor resolução (D = 3) ........ 109
6.8- As imagens coloridas recuperadas na nova proposta ............................. 113
xviii
xix
LISTA DE TABELAS
2.1- As ordens possíveis nas nove tiras ............................................................. 13
2.2- As ordens possíveis no caso de multi-planos ............................................ 15
4.1- O alfabeto de símbolos para codificação aritmética .................................. 49
5.1- Estrutura de registradores do CAA .............................................................. 57
5.2- Estrutura de registradores do DAA .............................................................. 58
6.1- Decomposição da estrutura de IEP .............................................................. 94
6.2- Decomposição do CIE do padrão JBIG ........................................................ 95
6.3- Decomposição do campo Ordem de CIE do padrão JBIG .......................... 95
6.4- Decomposição do campo Opções de CIE do padrão JBIG ........................ 95
6.5- Decomposição do DPIE do padrão JBIG ...................................................... 97
6.6- Decomposição do campo DTs,d,p ................................................................... 97
6.7- Decomposição do CIE utilizado neste trabalho .......................................... 98
6.8- Decomposição do DPIE utilizado neste trabalho ........................................ 99
6.9- Resultados de simulações do procedimento usual do JBIG ................... 101
6.10- Resultados de simulações da nova proposta ........................................... 102
6.11- Resultados de simulações do caso especial do JBIG ............................. 107
6.12- Resultados de simulações do algoritmo usual do JBIG ......................... 109
6.13- Resultados de simulações da nova proposta (imagem colorida) .......... 110
xx
xxi
ABREVIATURAS
ABAC: Adaptive Binary Arithmetic Coding. ABAD: Adaptive Binary Arithmetic Decoding. BUF: External buffer. CAA: Adaptive Arithmetic Encoder. CABA: Adaptive Binary Arithmetic Coding. DABA: Adaptive Binary Arithmetic Decoding. CCITT: The Consultative Committee of the International Telephone and
Telegraph. CIE: Image header. Com: Commentary. CT: Shift counter. CX: Context. DAA: Adaptive Arithmetic Decoder. DCP: Protected coded data. DPIE: Processed image data. DTNORM: Normal data end. DTRST: Reset at data end. FIFO: First In First Out. ESC: Escape. FSM: Finite State Machine. HITOLO: High to low. IEP: Processed image. ITU-T: International Telecommunication Union – Telecommunication
Standardization Sector. JBIG: Joint Bi-level Image Experts Group. JPEG: Joint Photographic Experts Group. LEAVE: Interleave multiple bit-planes. Liga: Lowest-resolution-layer two or three line template. LIFO: Last In First Out. LNT: Line not Typical. LPS: Less probable symbol. LRLTWO: Lowest-resolution-layer two-line template. LSZ: LPS size on coding interval. MLNT: Same LNT. MMR: Modified-Modified READ algorithm. MPS: More probable symbol. MPS/LPS: Conditional exchange. MS: Marker segment. MSE: Mean Squared Error. MTA: Adaptive Templates Movement. Nível: Maximum level value. PC: Coded Data.
xxii
PD: Deterministic Prediction. PDON: PD enable. PDPRIV: PD private. PDULTI: PD last. PGM: Portable GreyMap. PIX: Pixel. PPM: Portable PixelMap. PT: Typical Prediction. PTDON: Differential-layer PT enabled. PTBON: Lowest-layer PT enabled. RR: Resolution Reduction. SC: Stack counter. SEQ: Sequential. SMID: Index over stripe is in middle. SMPTE: Society of Motion Picture and Television Engineers. SNR: Signal to Noise Ratio. STUFF: Stuff. SWTCH: Switch. TA: Adaptive Template. TEMP: Temporary variable. TM: Model Template. Tipo: Type. VLENGTH: Variable length. VDP: Deterministic Prediction Value. VTP: Typical Prediction Value. WTSC: World Telecommunication Standardization Conference.
xxiii
SÍMBOLOS
CC: Base of current coding interval. DCamd,p: Layer coded data. CN (.): New base of current coding interval. Cs,d,p : Coded data for stripe s of resolution layer d of bit-plane p. DTs,d,p: Stripe coded data. D: Number of differential layer. DL: Number of initial resolution layer. IC: Current coding interval. Id,p : Image at resolution layer d of bit-plane p. Ii: Image at layer i. IN (.): New current coding interval. Li: Lines per stripe at layer i. MX: Maximum horizontal offset allowed for AT pixel. MY: Maximum vertical offset allowed for AT pixel. Pc: Cumulative probability. Pe: Estimate conditional probability. PL: Number of Bit-plans. PR: Relative probability. Ri: Sample resolution. S: Number of stripe per layer. ST[cx]: State of CX. Xi: Horizontal image size at layer i. Yi: Vertical image size at layer i. VMPS[cx]: Bit variable for more probable symbol relative to CX.
xxiv
Capítulo 1 - Conceitos Gerais 1
Capítulo 1
CONCEITOS GERAIS
1.1 Introdução
Com o avanço tecnológico da comunicação moderna, a demanda por
transmissão e armazenamento de dados cresce rapidamente. Esse crescimento requer
eficiência e rapidez de execução dos algoritmos usados nas técnicas pertinentes a essa
área. As pesquisas relacionadas com essas técnicas vêm ganhando atenção crescente
da comunidade científica e são objetos de estudos intensivos. Diversas técnicas vêm
sendo utilizadas e têm como base principalmente a compressão de dados,
possibilitando que as informações sejam transmitidas em menos tempo e/ou
armazenados no menor espaço possível. As técnicas de codificação sem perdas
(“lossless”) e com perdas (“lossy”) são duas formas usadas nesse campo [1],
aproveitando-se as facilidades atuais existentes nos métodos e nos algoritmos
propostos por diversos pesquisadores.
Atualmente, existe uma grande quantidade de trabalhos que apresenta técnicas
e métodos visando a redução da quantidade de dados (informações) associados a um
determinado sinal (áudio ou vídeo) a fim de se diminuir o volume do sinal (tempo de
transmissão, quantidade de memória física e largura de faixa). Algumas técnicas são
Capítulo 1 - Conceitos Gerais 2
implementadas utilizando-se imagens com escala de cinzas e imagens coloridas, tendo-
se em vista a codificação sem perdas. Entre elas pode-se ressaltar principalmente a
Codificação Aritmética Binária Adaptativa (CABA) [“Adaptive Binary Arithmetic Coding –
ABAC”]. Essa codificação foi adotada pelo grupo de pesquisa formado em 1988 a fim
de se estabelecer um padrão de compressão de dados denominado JBIG (“Joint Bi-
level Image Experts Group”). O padrão JBIG é próprio para codificação progressiva do
tipo adaptativo para imagens em 2 níveis (preto e branco) [2]. O JBIG foi aprovado pelo
WTSC (“World Telecommunication Standardization Conference”) em Março de 1993.
A motivação para este trabalho é a de melhorar a taxa de compressão e o
desempenho do sistema adotado no padrão JBIG. Alguns passos serão considerados
nas implementações do processo de codificação para se alcançar melhor compactação
de dados da imagem de entrada (imagem fonte). O codificador aritmético no padrão
JBIG recebe apenas imagens binárias de 2 níveis (“bilevel”) [2], isto é, o princípio do
padrão JBIG é a codificação de imagens de 2 níveis.
Neste trabalho, pretende-se implementar a codificação progressiva do padrão
JBIG para atender imagens com escala de cinzas e imagens coloridas. Para que o
padrão JBIG realize o processo de codificação de uma imagem desses tipos, a imagem
deve ser dividida em vários planos de bits. Cada plano é tratado pelo algoritmo de
codificação como uma imagem de 2 níveis. Além disso, pode-se implementar um caso
especial de codificação para uma imagem com escala de cinzas, onde o modo
seqüencial progressivo-único será usado. Nesse caso, cada plano de bits é dividido em
várias camadas de resolução.
Capítulo 1 - Conceitos Gerais 3
O método proposto será aplicado tanto para a imagem com escala de cinzas
quanto para a imagem colorida. A hierarquia presente no codificador é trabalhada no
decodificador.
Assim, decidiu-se para o presente trabalho utilizar o algoritmo de codificação
CABA a fim de se implementar a técnica de compressão baseada no padrão JBIG. O
modo progressivo do padrão JBIG foi usado e adaptado para imagem com escala de
cinzas e também para imagem colorida. Isso é discutido mais amplamente no capítulo
2, onde se abordam diversos aspectos relacionados com a técnica escolhida e o padrão
JBIG. No capítulo 3, explica-se o tipo de modelo usado e seu template para as
camadas diferenciais de resolução bem como para a camada de menor resolução. No
capítulo 4, discutem-se as técnicas de codificação aritmética binária e não binária. As
rotinas para implementação da técnica de codificação progressiva são explicadas no
capítulo 5.
As técnicas de codificação são usadas para se reduzir a quantidade de
informação necessária para a transmissão e armazenamento de dados referentes a
uma imagem. Portanto, tem-se como objetivo a representação de informação da
imagem original através de códigos mais eficientes. Essa redução pode ser uma função
da estatística da imagem. No capítulo 6, discute-se o formato da imagem fonte usada
para se testar e avaliar a técnica de codificação progressiva.
1.2 A Compressão e Suas Aplicações em Telecomunicações
Na área de codificação de imagens, os custos de transmissão e de
armazenamento de informação são tratados com muita atenção por um grande número
Capítulo 1 - Conceitos Gerais 4
de pesquisadores pelo fato de que são fatores importantes em qualquer técnica de
compressão. Tais parâmetros são levados em consideração nas aplicações que
requerem compressão (codificação) de dados. Portanto, surgiram propostas de vários
métodos de compressão de informação de imagem abordando os dois temas. Uma
classificação básica desses métodos se chama compressão física (codificação
preditiva) [3,4]. Nesse caso, explora-se a redundância presente na informação,
reduzindo-se a taxa de bits antes dos dígitos binários serem entregues a um meio de
transmissão. A redundância é uma característica que está relacionada com fatores tais
como aleatoriedade, predictibilidade, similaridade e outros existentes na informação da
imagem.
Para transmissão de informação [4], as técnicas de compressão fornecem
diversos benefícios ao projetista de rede. Elas são úteis para redução do tempo real
requerido para se enviar os dados, ou seja, para se reduzir a taxa de bits na linha de
transmissão que implique na redução de erros. Pode-se ter economia de custo
associada ao envio de menos dados. Aumenta-se assim a eficiência devido à tendência
de se ter uma redução de jornadas extras de trabalho para o envio da informação
completa. Além disso, fornecem um nível de segurança pela conversão de texto para,
por exemplo, o padrão ASCII.
Para armazenamento de informação, as técnicas de compressão trabalham no
sentido de se reduzir a quantidade de dados que está sendo armazenada, ou seja, há
ganho no espaço físico. Assim, o tempo de execução do programa pode ser reduzido.
Dessa forma, as técnicas de compressão podem ser usadas em várias
aplicações, por exemplo, para transmissão de imagem de TV comercial via satélite,
transmissão digital de sinais de vídeo (telefonia convencional), transmissão de dados
Capítulo 1 - Conceitos Gerais 5
via fac-símile, transmissão na rede mundial de comunicações (internet), imagens
geradas por computadores, comunicação entre computadores, imagens escaneadas,
armazenamento de imagens médicas em sistemas de monitoramento de pacientes.
De modo especial, várias técnicas são usadas para se comprimir informações
destinadas a transmissão por fac-símile. Um método eficiente é obtido ao se designar
códigos pré-definidos para diferentes fileiras de pixels em preto e branco. Os códigos
substituem cada seqüência de fileiras de pixels encontrada em cada linha de varredura.
Essa técnica é fundamentada na codificação de Huffman modificada [4]. Outro método
mais eficiente ainda é obtido ao se designar códigos durante o processo de codificação.
Esse método é utilizado na codificação aritmética [5]. O objetivo é preparar a imagem
comprimida para transmissão ou armazenamento com o menor número possível de
bits, preservando-se o nível da qualidade (requerida para a aplicação específica
relacionada com determinado serviço).
1.3 A Técnica de Codificação Sem Perdas
A codificação sem perdas surge como opção real, sem provocar a degradação
na imagem [6]. A recuperação dos dados codificados deve ser efetuada sem
degradações acumulativas, isto é, a imagem recuperada é idêntica a transmitida ou
armazenada. Portanto, os dados recuperados são exatamente iguais aos dados da
imagem original. O processamento nesse caso é sem qualquer erro, evitando-se assim
as aproximações geralmente feitas na codificação não exata. Nesse caso, a relação
sinal/ruído (SNR - “Signal to Noise Ratio”) é infinita e o erro quadrático médio (MSE -
“Mean Squared Error”) é zero, já que a degradação é nula. Um exemplo prático da
Capítulo 1 - Conceitos Gerais 6
codificação sem perdas é a codificação usada para o fac-símile de documento – Grupo
3 do CCITT (“The Consultative Committee of The International Telephone and
Telegraph”). Nessa aplicação, os vários comprimentos das seqüências de 0`s e 1`s têm
palavras código cujos comprimentos seguem suas probabilidades de ocorrência [7], ou
seja, a seqüência com maior probabilidade de ocorrência tem palavra a código mais
curta. Esse método é chamado de codificação entrópica.
Reduzir a taxa de transmissão bem como a capacidade de memória de
armazenamento é uma questão que está intimamente ligada à finalidade do serviço da
técnica de codificação seja para transmissão ou para armazenamento. Sendo assim, a
eficiência da técnica de codificação é medida pela taxa de informação média, ou seja,
pela comparação entre o número de bits necessário para a transmissão com o número
de bits da imagem original, o qual é dado pela sua entropia, ou quantidade de
informação [8]. Portanto, a terminologia empregada para se examinar ou avaliar a
eficiência da técnica de compressão abordada neste trabalho é dada a seguir:
• comprimido arquivo do tamanho
original arquivo do tamanho Compressãode Fator = (1.1)
• original arquivo do tamanho
comprimido arquivo do tamanho méritode Figura = (1.2)
• méritode Figura- 1redução da Fração = (1.3)
• 100*reduçãodaFração Compressão % = % (1.4)
• pixelsem original tamanho
bitsem comprimido tamanho bits de Taxa = (1.5)
De acordo com a equação (1.2), quanto menor a figura de mérito, mais eficaz é a
técnica de compressão empregada. Algumas imagens padronizadas pelo SMPTE
Capítulo 1 - Conceitos Gerais 7
(“Society of Motion Picture and Television Engineers”) foram utilizadas para se testar a
técnica de compressão abordada. Tais imagens são chamadas de Bars, Bird, Cozinha,
Sala, Clock, Cameraman, Bridge, Karen, Jelly_beans1, Couple, Pássaro, Airplane e
Lenna. No caso de imagem com escala de cinzas, a imagem é digitalizada em 8 bits por
amostra (pixel). No caso de imagem colorida, cada pixel contem os três sinais RGB
(“Red”, “Green” e “Blue”). Cada sinal é digitalizado em 8 bits. Portanto, a imagem é
digitalizada em 24 bits por amostra.
Capítulo 1 - Conceitos Gerais 8
Capítulo 2 - O Padrão JBIG 9
Capítulo 2
O PADRÃO JBIG
2.1 Introdução
A exigência de redução do tempo de transmissão ou da quantidade do espaço
de armazenamento de dados provocou o aparecimento de diversos tipos de padrões
mundiais de compressão. Um desses padrões é o JBIG. Ele foi preparado originalmente
para codificação progressiva de imagens em 2 níveis (preto e branco).
A idéia do sistema de codificação progressiva é transmitir uma imagem
comprimida, primeiro enviando-se os dados compactados em uma versão de resolução
reduzida da imagem (camada de menor resolução) e depois enriquecendo-se a mesma
quando for necessário através da transmissão adicional de mais dados compactados
(camadas diferenciais de resolução), os quais complementam os dados já transmitidos
anteriormente. A regulamentação (“Recommendation | International Standard”) define
para um método de codificação, os seguintes modos: progressivo, seqüencial
compatível-progressivo, seqüencial progressivo-único. Neste trabalho, o modo
seqüencial progressivo-único foi aplicado na codificação de imagem com escala de
cinzas, em caso especial. Os modos progressivo e seqüencial compatível-progressivo
Capítulo 2 - O Padrão JBIG 10
foram aplicados na codificação de imagem com escala de cinzas, bem como na
codificação de imagem colorida.
Entretanto, o esforço neste trabalho é dedicado para a implementação de quatro
sub-blocos que fazem parte do padrão JBIG, isto é, o sub-bloco “Redutor de
Resolução”, o sub-bloco “Predição Típica”, o sub-bloco “Template Modelo” e o sub-
bloco “Codificador Aritmético Adaptativo”.
2.2 O Modo Progressivo
O padrão JBIG define um método para codificação sem perdas de imagens
paradas (estáticas), em 2 tons, ou seja, basicamente o método de codificação foi usado
para imagens em preto e branco. Neste trabalho, desenvolveu-se um método para
imagens com escala de cinzas e imagens coloridas, isto é, a codificação progressiva
pode ser usada também para se codificar imagens com escala de cinzas e imagens
coloridas [9]. Portanto, desenvolveu-se um esquema baseado no padrão JBIG que
atenda esse tipo de imagens e que resulte em uma codificação sem perdas [10]. Isso
se torna possível pela utilização da codificação aritmética binária adaptativa (CABA) e
pelo uso de algoritmo de redução da resolução.
Para realizar a codificação progressiva deve-se implementar um algoritmo que
divide a imagem original em vários planos de bits (PL). Em seguida, o algoritmo de
redução da resolução divide cada plano novamente em determinados números de
camadas de resolução. Conseqüentemente, as camadas são codificadas pelo algoritmo
de CABA uma a uma seqüencialmente [11]. A redução de resolução na codificação é
Capítulo 2 - O Padrão JBIG 11
realizada a partir das camadas de maior para as de menor resolução, enquanto que a
decodificação é realizada a partir das camadas de menor para as de maior resolução.
Sendo assim, as camadas de resolução são enviadas num modo progressivo
sendo também a camada codificada seqüencialmente, ou seja, ela é varrida da
esquerda para a direita e de cima para baixo (modo de “raster”). Para uma aplicação de
codificação seqüencial progressivo-único, somente a imagem de menor resolução é
codificada sem nenhuma referência às camadas de resolução e depois enviada, sendo
possível criar um trem de pulsos no padrão JBIG. Por outro lado, para uma aplicação de
codificação seqüencial compatível-progressivo, cada camada diferencial de resolução é
codificada seqüencialmente, enquanto que essas camadas são enviadas num modo
progressivo.
2.2.1 Estrutura Geral
A partir do que foi frisado anteriormente, antes de se realizar a operação de
compressão, a imagem é dividida em planos de bits PL. O número de planos de bits
depende de quantos bits por pixel são usados. Se a mensagem ou o pixel tem 8 bits,
então existe a possibilidade de se ter 8 planos de bits. Cada plano de bits é dividido em
camadas, resultando em duplicações com resoluções diferentes (D). Essas duplicações
são chamadas camadas diferenciais de resolução. Segundo o padrão JBIG, cada
camada de resolução pode ser dividida em faixas horizontais chamadas tiras e em
determinado número de linhas, sendo que as tiras na mesma camada de resolução são
iguais. Entretanto, neste trabalho não foi aplicada a técnica de divisão de camadas em
tiras.
Capítulo 2 - O Padrão JBIG 12
De modo geral, seja S o número de tiras em cada camada de resolução, onde S
é igual para todas as camadas de resolução. ID será referenciada como uma imagem da
camada de maior resolução (imagem de entrada); então a sua dimensão horizontal será
XD; sua dimensão vertical será YD; sua resolução de amostragem será RD (pontos-por-
polegada); e o número de linhas em cada tira será LD. A Figura (2.1) mostra a
decomposição quando se tem 1 plano de bits, 3 camadas de resolução e 3 tiras por
camada, e a Figura (2.2) mostra a decomposição quando se tem 2 planos de bits, 3
camadas de resolução e 3 tiras por camada.
R0 = 25 dpi d0 = I0
R1 = 50 dpid1 = I1
R2 = RD = 100 dpi d2 = I2 = ID
YD
XD
6
7
8
4
3
5
0
1
2
LD
S0
S1
S2 S2
S1
S0 S0
S1
S2
Fig. (2.1)- Decomposição fornecida pela codificação progressiva de: 1 plano de bits, 3 camadas de resolução e 3 tiras [2].
R0 = 25 dpi d0 = I0
PL= 1 (MSB)
PL= 0 (LSB)
R1 = 50 dpid1 = I1
R2 = RD = 100 dpi d2 = I2 = ID
13
12
14
15
16
17
06
07
08
09
10
11
00
01
02
03
04
05
S0
S1
S2
Fig. (2.2)- Decomposição fornecida pela codificação progressiva de: 2 planos de bits, 3 camadas de resolução e 3 tiras [2].
Capítulo 2 - O Padrão JBIG 13
A ordem do processo de codificação progressiva depende de algumas variáveis
tanto para a forma que tem somente 1 plano de bits quanto para a forma que tem mais
do que 1 plano de bits. A primeira forma (de 1 plano de bits) depende de duas variáveis
que são:
• A primeira é a SEQ bit (“Sequential”). Nesse caso, os dados são tratados pelo
codificador do JBIG na forma seqüencial iniciando-se pela camada de menor
resolução e indo para de maior resolução (ou vice-versa). Pega-se os dados da
primeira tira seguidos pelos dados da segunda tira e assim por diante. Então se
passa para a segunda camada de resolução repetindo-se o mesmo processo.
Nesse caso, o valor da SEQ = 0. Portanto, a função da variável SEQ é arrumar a
ordem das tiras.
• A segunda variável é a HITOLO bit (“High to Low”). Nesse caso, o codificador do
JBIG codifica os dados começando-se pela camada de menor resolução e indo
para de maior resolução. Nesse caso, o valor da HITOLO = 0. Portanto, HITOLO
arruma a ordem das camadas de resolução.
A Tabela (2.1) mostra as possibilidades de ordem de Figura (2.1).
Tab. (2.1)- As ordens possíveis nas nove tiras [2].
HITOLO SEQ Exemplos de ordem
0 0 0,1,2,3,4,5,6,7,8
0 1 0,3,6,1,4,7,2,5,8
1 0 6,7,8,3,4,5,0,1,2
1 1 6,3,0,7,4,1,8,5,2
Capítulo 2 - O Padrão JBIG 14
A segunda forma (de mais do que 1 plano de bits, por exemplo, 2 planos de bits)
depende de quatro variáveis. Duas delas, são as mesmas que foram citadas para a
primeira forma, sendo que as outras duas variáveis são:
• Primeira variável ILEAVE bit (“Interleave Multiple Bit-planes”). Portanto, ILEAVE
arruma a ordem dos Planos de bits. Quando ILEAVE = 1 indica que o bit está
sendo ligado, ou seja, sempre os dados de tiras do maior plano de bits seguidos
pelos do menor plano de bits na mesma operação. Dessa forma, a codificação
dentro de qualquer camada de resolução começa pelos dados do maior plano de
bits (MSB) indo para os de menor plano de bits (LSB).
• Segunda, a variável SMID bit (“Index Over Stripe is in Middle”). Quando SMID =
1 indica que S (número de tiras por camada) está no meio, ou seja, inicia-se a
codificação dos dados pelas primeiras tiras nos planos de bits (MSB) de mesma
resolução, ou no mesmo plano de bits (começando por MSB) em todas as
resoluções. Isso é mostrado de maneira mais clara na Tabela (2.2), a qual
mostra também as possibilidades de ordem da Figura (2.2).
Devido ao fato de que a divisão de camadas em tiras não está sendo usada
nesse trabalho, as varáveis SEQ e SMID não são usadas. Também, os dados
compactados (palavras código) em CS,d,p para a tira s da camada de resolução d e do
plano de bits p são independentes da ordem de tiras, ou seja, a imagem de entrada não
está sendo dividida em tiras. Portanto, os dados compactados serão referenciados por
Cd,p. Sendo assim, a ordem de número 1 da tabela (2.2) é usada neste trabalho.
Capítulo 2 - O Padrão JBIG 15
Tab. (2.2)- As ordens possíveis no caso de multi-planos [2].
No. HITOLO SEQ ILEAVE SMID Exemplos de ordem
1 0 0 0 0 (00,01,02 06,07,08 12,13,14)(03,04,05 09,10,11 15,16,17)
2 0 0 1 0 (00,01,02 03,04,05) (06,07,08 09,10,11) (12,13,14 15,16,17)
3 0 0 1 1 (00,03 01,04 02,05) (06,09 07,10 08,11) (12,15 13,16 14,17)
4 0 1 0 0 (00,06,12 03,09,15) (01,07,13 04,10,16) (02,08,14 05,11,17)
5 0 1 0 1 (00,06,12 01,07,13 02,08,14)(03,09,15 04,10,16 05,11,17)
6 0 1 1 0 (00,03 06,09 12,15) (01,04 07,10 13,16) (02,05 08,11 14,17)
7 1 0 0 0 (12,13,14 06,07,08 00,01,02)(15,16,17 09,10,11 03,04,05)
8 1 0 1 0 (12,13,14 15,16,17) (06,07,08 09,10,11) (00,01,02 03,04,05)
9 1 0 1 1 (12,15 13,16 14,17) (06,09 07,10 08,11) (00,03 01,04 02,05)
10 1 1 0 0 (12,06,00 15,09,03) (13,07,01 16,10,04) (14,08,02 17,11,05)
11 1 1 0 1 (12,06,00 13,07,01 14,08,02)(15,09,03 16,10,04 17,11,05)
12 1 1 1 0 (12,15 06,09 00,03) (13,16 07,10 01,04) (14,17 08,11 02,05)
Capítulo 2 - O Padrão JBIG 16
2.3 As Vantagens da Técnica de Codificação do JBIG
A codificação progressiva é do tipo adaptativa. Essa adaptação às características
da imagem torna o método robusto em relação ao tipo da imagem. Os benefícios da
codificação do padrão JBIG são [2,9]:
• O padrão tem eficiência de compressão superior ao padrão G3/G4 (“fac-símile”)
e às vezes alcança desempenho acima do padrão JPEG (“Joint Photographic
Experts Group”).
• Em imagens escaneadas de caracteres impressos, as taxas de compressão
observadas têm sido da ordem de 1,1 a 1,5 vezes maiores do que aquelas
obtidas pelo algoritmo de codificação MMR (“Modified-Modified READ”)
[Recomendações T.4 (G3) e T.6 (G4)].
• Em imagens de caracteres impressos geradas no computador, a taxa de
compressão observada tem sido em torno de 5 vezes maior.
• É possível projetar uma aplicação com uma base de dados comum, a qual pode
servir eficientemente dispositivos de saída com capacidades de resolução muito
diferentes.
• No caso de uma imagem já existente numa tela, se um enriquecimento adicional
da resolução é desejado, então, somente a informação extra de enriquecimento
para a resolução necessária tem que ser enviada e decodificada.
• Devido ao estágio extra de enriquecimento de resolução atuar sobre a imagem já
existente, o usuário tem a possibilidade de reconhecer rapidamente a imagem
enquanto está sendo construída antes de se transmitir todas as informações da
Capítulo 2 - O Padrão JBIG 17
mesma, permitindo ao usuário interromper o processo de construção da imagem
se isso for desejado (como está sendo usado na internet).
2.4 Blocos de Codificação do JBIG
O codificador JBIG, em cada plano de bits, pode ser decomposto em vários
blocos como está mostrado na Figura (2.3), independentemente do número de planos
de bits. Os blocos de processamento de camada diferencial e redução de resolução na
Figura (2.3) são idênticos em funções. Por isso somente uma descrição da operação de
uma camada é necessária, além do bloco codificador de camada de menor resolução.
Para tal descrição, a imagem de chegada será referenciada como uma imagem de alta
resolução (ID), a imagem de saída como uma imagem de baixa resolução (ID-1) e a
palavra código como CD,p.
ID-1 Codificador de
Camada Diferencial
e Redutor
de Resolução
ID
ID-2Codificador
de Camada
Diferenciale
Redutor de
Resolução
Codificador
de Camada
de Menor
Resolução
I0
C0,p
CD-1,p
CD,p
Fig. (2.3)- Blocos do codificador [2].
Capítulo 2 - O Padrão JBIG 18
2.4.1 Sub-blocos do Codificador de Camada Diferencial, do Redutor de Resolução e da Camada de Menor Resolução. O algoritmo de codificação divide a imagem de entrada em planos de bits, e cada
plano é dividido em camadas de resolução pelo Redutor de Resolução (RR). O pixel a
ser codificado deve ser passado pela Predição Típica (PT) para decidir se é necessário
ou não codificá-lo. As camadas serão analisadas pelo Template Modelo (TM) para se
determinar a estatística do pixel a ser codificado. Conseqüentemente, os pixels serão
enviados um a um para o Codificador Aritmético Adaptativo (CAA) para se criar o
código que será transmitido ou armazenado. Esse processo de codificação é feito
recursivamente, ou seja, o mesmo processo é repetido em cada iteração destinada à
codificação de um dado pixel. Existem mais dois sub-blocos que não foram abordados
neste trabalho, que são: sub-bloco Predição Determinística (PD) e sub-bloco Template
Adaptativo (TA).
A Figura (2.3) pode ser decomposta em dois conjuntos de sub-blocos. Incluindo-
se os dois sub-blocos PD e TA, o primeiro conjunto está mostrado na Figura (2.4) para
o bloco codificador de camada diferencial. O segundo está mostrado na Figura (2.5)
para o bloco codificador de camada de menor resolução. No segundo caso, os sub-
blocos RR e PD não são aplicáveis e os sub-blocos PT, TM e TA são diferentes porque
não existe nenhuma camada de menor resolução para ser usada como referência.
Capítulo 2 - O Padrão JBIG 19
RR
CAA
PT TM
Imagem de alta Resolução
(Id,p)
VTP
LNT
CX
Imagem Reduzida
PD TA
VDP
Id-1,p
MTA
Cd,p
Fig. (2.4)- Codificador de camada diferencial e redutor de resolução [2].
CAA
PT TM
I0,p
VTP
MLNT
CXTA
MTA
C0,p
Fig. (2.5)- Codificador de camada de menor resolução [2].
Tem-se:
Id,p: Imagem na camada d do plano p;
MTA: Movimento adaptativo do Template;
LNT: Linha não típica (sinal);
MLNT: Mesmo sinal LNT;
VTP: Valor típico de predição (sinal);
VDP: Valor determinístico de predição (sinal).
Sabe-se que para qualquer técnica de compressão, principalmente na
codificação aritmética, existem três unidades principais denominadas: o modelo, a
distribuição da freqüência relativa (probabilidade) do pixel e o codificador [12]. Portanto,
Capítulo 2 - O Padrão JBIG 20
o esforço foi dedicado somente para a implementação dos quatro sub-blocos (RR, TM,
PT e CAA) que fazem parte do padrão JBIG no lado do codificador e que são
necessários para cada plano de bits. Tem-se:
1) Sub-bloco Redutor de Resolução (RR)
Em cada plano, esse sub-bloco recebe uma imagem de alta resolução, e se cria
uma outra de baixa resolução com qualidade tão próxima quanto possível da imagem,
correspondente a metade de todas as linhas e metade de todas as colunas da imagem
de alta resolução, produzindo-se assim as camadas de diferentes resoluções (D). Esse
número D foi implementado no “software” para que seja controlado pelo usuário e pode
ser um número inteiro entre valores 0 e 8, e não é aconselhável escolher um número
fora desse limite. Um meio óbvio de redução da resolução de uma dada imagem por um
fator de 2 em cada dimensão é subamostrá-la tomando-se todas as linhas e todas as
colunas. A subamostragem é simples, mas cria imagens de qualidade subjetiva pobre,
pois alguns dos detalhes das imagens podem estar sendo freqüentemente perdidos.
Dependendo do valor D, o algoritmo de RR pode produzir de I0 a ID-1 camadas de
resolução. A redução de resolução é feita a partir das camadas de maior para as de
menor resolução, sendo que o processo de decodificação é realizado de maneira
inversa. Além disso, o processo é feito seqüencialmente. Por exemplo, para uma
imagem de tamanho 1728X2376 pixels e com valor de D = 3, para cada plano, o
algoritmo de RR divide a imagem original em:
• Imagem I2 (maior resolução) com tamanho 1728X2376 pixels.
Capítulo 2 - O Padrão JBIG 21
• Imagem I1 (média resolução) com tamanho 864X1188 pixels, ou seja, a metade
de I2.
• Imagem I0 (menor resolução) com tamanho 432X594 pixels, ou seja, a metade
de I1.
Note que a imagem I2 é igual à imagem original (resolução total).
Para produzir cada pixel na camada de baixa resolução, o algoritmo de RR
realiza uma filtragem utilizando-se 4 pixels, na camada de alta resolução, circundantes
ao pixel a ser produzido P?, 5 pixels vizinhos deles nas mesmas linhas e na linha prévia
e 3 pixels na camada de baixa resolução na mesma linha e na linha antecedente do
pixel P?, como está mostrando a Figura (2.6) [2]. Portanto, o valor previsto do pixel P?
pode ser determinado como sendo o seguinte:
P? = L(11) L(10) L(9) H(8) H(7) H(6) H(5) H(4) H(3) H(2) H(1) H(0) (2.1)
onde,
L(.): valor correspondente a um bit na camada de baixa resolução;
H(.): valor correspondente a um bit na camada de alta resolução.
O valor do P? obtido será indexado para um tom (“0” ou “1”) numa tabela
[Apêndice A1] construída pelo padrão JBIG [2].
Capítulo 2 - O Padrão JBIG 22
L(9)L(9)H(0)H(1)H(2)
H(3)H(4)H(5)
H(8) H(7) H(6)L(10)L(10)
P?P?
L(11)L(11)
L(9)L(9)H(0)H(1)H(2)
H(3)H(4)H(5)
H(8) H(7) H(6)L(10)L(10)
P?P?
L(11)L(11)
Fig. (2.6)- Os pixels usados para se determinar o valor do pixel na camada de baixa resolução.
2) Sub-bloco Predição Típica de Camada Diferencial (PT)
A função desse sub-bloco é procurar pela região de cor sólida (uniforme), ou
seja, os pixels que carregam o mesmo nível de cor. Quando um dado pixel corrente de
alta resolução a ser codificado encontra-se nessa região, nenhum processamento
normalmente feito nos outros sub-blocos é necessário, isto é, o dado pixel não precisa
ser codificado. O propósito primário desse sub-bloco é aumentar a velocidade das
implementações. A idéia usada neste trabalho consiste no seguinte:
Internamente, o sinal VTP foi interpretado para um valor, como opção, fornecido pelo
usuário, indicando a habilitação da função desse sub-bloco, ou seja, se o sub-bloco PT
pode ser usado ou não. Se for habilitado o uso do sub-bloco PT, então no início de
cada linha, o algoritmo realiza uma procura pela região que tem a mesma cor do pixel a
ser codificado (região uniforme), comparando-se a mesma linha com a linha
antecedente. Caso encontre a semelhança na cor, o sinal LNT será enviado ao
codificador para se evitar a codificação da linha que carrega o pixel a ser codificado. O
Capítulo 2 - O Padrão JBIG 23
codificador adiciona um sinal aos códigos a fim de que o decodificador possa recuperar
os pixels dessa linha. Caso contrário, a linha corrente será codificada normalmente.
3) Sub-bloco Template Modelo (TM)
O sub-bloco recebe o pixel a ser codificado bem como alguns pixels vizinhos a
ele e calcula um número inteiro chamado contexto (CX). O contexto é enviado para o
sub-bloco do codificador aritmético adaptativo CAA. Esse processo é feito
sucessivamente para cada pixel da seqüência (PIX) que está sendo codificada. Essa
seção será explicada de maneira mais detalhada no capítulo 3.
4) Sub-bloco Codificador Aritmético Adaptativo (CAA)
O sub-bloco CAA é um codificador binário de entropia. Ele observa a saída do
sub-bloco PT para determinar se é mesmo necessário codificar um dado pixel. Se for
necessário, então o CAA observa o contexto CX e utiliza o seu estimador de
probabilidade interno, através do uso de uma tabela de estimação de probabilidade [2].
Em seguida estima a probabilidade condicional adaptativa do pixel corrente. Esse sub-
bloco será explicado com exemplos no capítulo 4.
Para se ter uma visão geral, mais dois sub-blocos (PD e TA), que não foram
implementados nesse trabalho, são explicados a seguir:
Capítulo 2 - O Padrão JBIG 24
5) Sub-bloco Predição Determinística (PD)
O propósito desse sub-bloco é fornecer um ganho de codificação. Algumas
vezes ocorre que o valor de um pixel em uma camada de alta resolução, a ser
codificado, é deduzido a partir dos pixels vizinhos particulares na mesma camada e na
camada de baixa resolução. Quando isso ocorre, o sub-bloco PD sinaliza tal pixel e
evita-se o processo de codificação no sub-bloco CAA. O sub-bloco PD é um algoritmo
dirigido por tabelas PD; essas tabelas são fortemente dependentes do método
particular de redução de resolução usado.
6) Sub-bloco Template Adaptativo (TA)
A função desse sub-bloco é procurar a periodicidade na imagem. Quando se
encontra tal periodicidade, o template modelo é mudado. Ao mesmo tempo, uma
seqüência de controle MTA é adicionada ao fluxo de dados de saída (palavras código -
“output datastream”).
2.5 Blocos de Decodificação do JBIG
Os blocos do decodificador são análogos aos blocos do codificador. Para
qualquer plano de bits, os blocos recebem a seqüência de palavras código Cd,p e criam
as camadas de resolução, como está mostrado na Figura (2.7).
Capítulo 2 - O Padrão JBIG 25
ID-1 ID
ID-2
Decodificador
de
Camada
Diferencial
Decodificador
de Camada
de Menor
Resolução
I0
C0,p
CD-1,p
CD,p
Decodificador
de
Camada
Diferencial
Fig. (2.7)- Blocos do decodificador [2].
Uma descrição da operação de uma camada é agora necessária. Os blocos do
decodificador de camada diferencial e de menor resolução podem ser decompostos, no
caso geral, conforme estão mostrados nas Figuras (2.8) e (2.9) [2]. Observe que os
sub-blocos RR e TA não fazem parte do decodificador. Neste trabalho também não foi
usado o sub-bloco PD. Portanto, somente três sub-blocos do padrão JBIG são
necessários no lado do decodificador e esses foram implementados. Esses sub-blocos
são TM (é o mesmo daquele que foi usado pelo codificador CAA), PT e Decodificador
Aritmético Adaptativo (DAA).
DAA
TM PT
Imagem de Baixa Resolução (Id-1,p)
VTPLNT
CX
Cd,p
Imagem de Alta Resolução (Id,p)
PD
VDP
MTA
Figura (2.8) � Decodificador de camada diferencial.
Capítulo 2 - O Padrão JBIG 26
DAA
TM PT
VTPMLNT
CX
C0,p I0,p
MTA
Fig. (2.9)- Decodificador de camada de menor resolução.
O sub-bloco DAA recebe as palavras código Cd,p, o valor típico de predição VTP
e o contexto CX, e na saída recupera o fluxo de pixels PIX da imagem de alta
resolução.
2.6 Nova Proposta Para a Codificação Progressiva do JBIG
Na codificação CABA, o algoritmo divide a imagem de entrada (com escala de
cinzas ou colorida) em planos de bits (PL) correspondente ao número de bits por pixel.
Cada plano PL é tratado como se fosse uma imagem de 2 níveis (2 tons). Portanto,
pode-se aplicar a codificação aritmética do padrão JBIG em cada plano de bits (PL).
Um dos sub-blocos do codificador de camada diferencial é o sub-bloco redutor
de resolução RR. Esse sub-bloco faz parte da codificação progressiva, o qual divide
cada plano de bits (PL) em D camadas de resolução. As camadas são codificadas pelo
codificador CAA e transmitidas ou armazenadas uma a uma. Na decodificação DABA,
essas camadas são resgatadas do fluxo de palavra código PC e recuperadas pelo
decodificador DAA. Esse procedimento foi aplicado nas imagens de entrada com escala
de cinzas e coloridas.
Capítulo 2 - O Padrão JBIG 27
Um caso especial para a imagem com escala de cinzas foi implementado. Esse
caso serve para algumas aplicações que não exigem muitos detalhes nas imagens
recuperadas. Um exemplo de tais aplicações é a transmissão digital de sinais de vídeo
(Telefonia Convencional), ou seja, vídeo conferência. Nesse caso, o modo seqüencial
progresssivo-único foi utilizado. Dessa forma, a imagem de entrada foi dividida em
planos de bits (PL) e em camadas de resolução (D), sendo que somente a camada de
menor resolução (d0) foi codificada e transmitida ou armazenada. O resultado obtido
nesse caso é mostrado no capítulo 6.
Uma nova proposta foi implementada usando-se o mesmo procedimento do
método progressivo do padrão JBIG. A proposta é resumida em: o sub-bloco redutor de
resolução RR é transferido para o lado do decodificador ao invés de estar no
codificador, ou seja, esse sub-bloco será uma parte do decodificador de camada
diferencial. O processamento de codificação será aplicado para única camada de
resolução. Portanto, a imagem de entrada, de cada plano de bits, é codificada sem
dividí-la em camadas de resolução, isto é, a imagem é codificada com sua resolução
total. Nesse caso, pode-se diminuir o tamanho do arquivo compactado em relação ao
método usual, sendo esperado um melhor desempenho do sistema de compressão. O
algoritmo de codificação CABA somente envia o número de camadas de resolução (D)
desejado para o decodificador. Esse número D é escolhido pelo usuário. Através do
número D, o algoritmo do sub-bloco redutor de resolução RR divide cada plano de bits
(PL) em D camadas de resoluções diferentes, seguindo-se o mesmo procedimento que
foi usado quando o sub-bloco RR estava na codificação CABA.
A Figura (2.10) mostra o bloco do codificador de planos de bits. O codificador
recebe a imagem Ip do plano de bits p em sua resolução total, e cria os códigos (Cp).
Capítulo 2 - O Padrão JBIG 28
Codificadorde
Planos de Bits
Ip Cp
Fig. (2.10)- Bloco do codificador da nova proposta.
O codificador pode ser decomposto em vários sub-blocos como está mostrado
na Figura (2.11).
CAA
PT TM
Ip
VTP
MLNT
CX
Cp
Fig. (2.11)- Sub-blocos do codificador de planos de bits.
O bloco do decodificador de planos de bits é mostrado na Figura (2.12). A
decomposição está mostrada na Figura (2.13).
Cp
Decodificadorde
Planos de Bits
I0,p
ID-1,p
ID,p
Fig. (2.12)- Bloco do decodificador da nova proposta.
Capítulo 2 - O Padrão JBIG 29
RR
I0,p
ID-1,p
ID,p
DAA
TM PT
VTP
MLNT
CX
Cp Ip
Fig. (2.13)- Sub-blocos do decodificador de planos de bits.
A simulação dessa proposta é implementada tanto para a imagem com escala de
cinzas quanto para a imagem colorida. Os resultados são analisados comparando-se o
desempenho com a codificação progressiva usual que é usada no padrão JBIG. Esses
resultados são mostrados no capítulo 6.
Capítulo 2 - O Padrão JBIG 30
Capítulo 3 - A Estrutura do Modelo 31
Capítulo 3
A ESTRUTURA DO TEMPLATE MODELO
3.1 Introdução
Para qualquer técnica de compressão, existem três unidades principais
denominadas: o modelo, a probabilidade de ocorrência dos pixels e o codificador.
Neste trabalho, o modelo é separado da unidade do codificador. Ele proporciona
as características sobre os dados da imagem. O modelo determina o pixel atual a ser
codificado e seu contexto (CX). A operação de geração do contexto é feita
sucessivamente para cada pixel.
A estimação de estatística é calculada para cada contexto, sendo que ela pode
ser feita antes do processo de codificação como acontece na técnica de codificação de
Huffman [13], ou durante o processo de codificação como ocorre na técnica de
codificação aritmética. Essa estimação (probabilidade) é usada pela unidade do
codificador.
As codificações chamadas estatísticas são aquelas que utilizam técnicas de
compressão baseadas na estatística da imagem. Isso significa que se codificam os
dados com base na freqüência de ocorrência dos mesmos. Elas reduzem a
redundância entre os dados, e seu emprego minimiza o tamanho médio do código
Capítulo 3 - A Estrutura do Modelo 32
usado para representar os dados da imagem original. A codificação aritmética é
considerada um exemplo das diversas técnicas estatísticas de compressão de dados.
3.2 O Modelo
Vários tipos de modelos são usados nos sistemas de compressão. Esses
modelos dependem da aplicação usada. Por exemplo, no modelo simples chamado
sem memória (“memoryless”), os pixels são codificados de acordo com um código único
(como na codificação de Huffman). O modelo para os dados fonte às vezes especializa-
se na formulação da função recursiva para se obter uma fórmula da “Finite State
Machine” (FSM). O modelo FSM é a generalização de diversas versões de modelos
“Markov” para processo estocásticos, onde a probabilidade do pixel a ser codificado
depende dos valores observados previamente. Sendo assim, o contexto pode ser
definido como sendo um número inteiro calculado pela seqüência de pixels
antecedentes ao pixel a ser codificado. Ele é um estado determinado pelos pixels
passados sendo utilizado tanto para o codificador quanto para o decodificador.
O modelo de Markov usado neste trabalho é um modelo estacionário adaptativo.
A adaptação nesse modelo é realizada em função da ocorrência dos pixels (as
probabilidades associadas com os contextos) enquanto a seqüência de pixels está
sendo codificada, isto é, a probabilidade de cada pixel é determinada durante o
processo de codificação. Essa probabilidade muda de um estado para o próximo que
tenha mais informação sobre a seqüência de pixels a fim de se codificar o próximo pixel
[2].
Capítulo 3 - A Estrutura do Modelo 33
3.3 A Estrutura do Modelo Usado
Neste trabalho, na codificação progressiva, o contexto é determinado pelas
tonalidades (níveis binários) de pixels particulares na imagem de alta resolução, pelos
pixels particulares na imagem de baixa resolução e pela fase espacial do pixel a ser
codificado. A fase espacial descreve a orientação do pixel de alta resolução com
relação ao pixel de baixa resolução correspondente. Através do contexto, o algoritmo
do codificador CAA localiza a estimativa de probabilidade do pixel a ser codificado.
Os modelos de Markov de décima ordem e de décima segunda ordem são
usados tanto para o codificador quanto para o decodificador. A estrutura do modelo
(Template Modelo) é construída em várias formas [14,15]. O padrão JBIG fornece duas
formas de Template para se calcular o contexto [2,9], as quais contêm 10 e 12 pixels
vizinhos e circundantes, na mesma linha e nas linhas prévias, ao pixel a ser codificado.
Esses pixels têm forte relação com o pixel que está sendo codificado. As duas formas
da estrutura de template modelo são explicadas a seguir:
A primeira forma: ela é usada para se codificar as camadas de menor resolução. Esse
Template pode ser composto de duas ou de três linhas de 10 pixels antecedentes ao
pixel a ser codificado (Markov de décima ordem), como estão mostradas nas Figuras
(3.1) e (3.2).
P (t-M-3) P (t-M-2) P (t-M-1) P (t-M) P (t-M+1)
P (t-3)
P (t-M+2)
P (t-2) P (t-1) P (t) P (t+1)
Fig. (3.1)- Template Modelo de Markov de duas linhas.
Capítulo 3 - A Estrutura do Modelo 34
P (t-2M-1) P (t-2M) P (t-2M+1)
P (t-M-2) P (t-M-1) P (t-M) P (t-M+1) P (t-M+2)
P (t-1) P (t) P (t+1)
Fig. (3.2)- Template Modelo de Markov de três linhas.
onde,
t: posição do pixel P(t);
t+1: posição do pixel P (t+1) a ser codificado; não faz parte do Template;
M: número de pixels por linha;
P (t-M): o pixel acima do pixel que a ser codificado.
A segunda forma: ela é usada para se codificar as camadas diferenciais de resolução.
O Template contém 12 pixels, 6 deles estão na imagem de alta resolução, 4 estão na
imagem de baixa resolução e 2 na fase espacial do pixel a ser codificado (Markov de
décima segunda ordem), conforme mostrado na Figura (3.3).
Capítulo 3 - A Estrutura do Modelo 35
H(5)
H(8)
H(4)
H(9)
L(3)
H(7)
P?
H(6)
L(1) L(0)
L(2)
H(5)
H(8)
H(4)
H(9)
H(7)
P?
H(6)
L(1) L(0)
L(2) L(3)
H(5)
H(8)
H(4)
H(9)
L(3) H(7)
P?
H(6)
L(1) L(0)
L(2)
H(5)
H(8)
H(4)
H(9)
H(7)
P?
H(6)
L(1) L(0)
L(2) L(3)
Fase 0
Fase 2
Fase 1
Fase 3
Fig. (3.3)- Template Modelo de Markov para as 4 fases [2].
3.4 O Cálculo do Contexto
O contexto é um estado calculado pela seqüência de pixels circundantes ao pixel
a ser codificado, sendo que os mesmos têm forte dependência com o pixel em questão.
O contexto será um valor inteiro entre 210 valores diferentes (para a camada de menor
resolução), onde o expoente 10 é um número inteiro dos pixels prévios do pixel a ser
codificado no template, ou um valor entre 212 valores diferentes (para as camadas
diferenciais de resolução). Cada pixel no Template Modelo corresponde a um bit no
contexto.
Capítulo 3 - A Estrutura do Modelo 36
Usando-se as estruturas de Template Modelo das Figuras (3.1) a (3.3), os pixels
são compartilhados para se determinar o valor do contexto CX associado ao pixel que
está sendo codificado, como ilustrado a seguir:
Para a camada de menor resolução:
De duas linhas: CX = P (t-M-3) P (t-M-2) …… P (t-M+2) P (t-3) …… P (t) (3.1)
De três linhas: CX = P (t-2M-1) ... P (t-2M+1) P (t-M-2) … P (t-M+2) P (t-1) P (t) (3.2)
Para as camadas diferenciais de resolução:
CX = F(11) F(10) H(9) H(8) H(7) H(6) H(5) H(4) L(3) L(2) L(1) L(0) (3.3)
onde,
F(11) F(10): dois bits da fase especial são atribuídos como sendo:
F(11) = 0 e F(10) = 0 para Fase 0; F(11) = 0 e F(10) = 1 para Fase 1;
F(11) = 1 e F(10) = 0 para Fase 2; F(11) = 1 e F(10) = 1 para Fase 3.
3.5 Comentários
Dois tipos de estruturas de modelos de template são oferecidos pelo padrão
JBIG. O primeiro tipo destina-se à camada de menor resolução. O padrão fornece duas
estruturas, uma de duas linhas e outra de três linhas. Dez pixels antecedentes ao pixel
a ser codificado na linha atual e nas linhas prévias, tanto na estrutura de 2 linhas
quanto na estrutura de 3 linhas, são usados para se calcular o contexto (CX) do modelo
de Markov de décima ordem. O segundo é usado nas camadas diferenciais. Seis pixels
Capítulo 3 - A Estrutura do Modelo 37
antecedentes ao pixel a ser codificado na linha atual e nas linhas prévias da camada de
alta resolução, quatro pixels da camada de baixa resolução e dois pixels da fase
espacial são usados para se calcular o contexto (CX) do modelo de Markov de décima
segunda ordem.
O contexto é um número inteiro calculado no bloco template modelo e enviado
para o codificador CAA a fim de se realizar o processo de codificação. O codificador
utiliza o contexto para determinar a estimativa de probabilidade condicional do pixel que
está sendo codificado. O mesmo contexto é usado no decodificador DAA.
Capítulo 3 - A Estrutura do Modelo 38
Capítulo 4 - A Codificação Aritmética
39
Capítulo 4
CODIFICAÇÃO E DECODIFICAÇÃO ARITMÉTICA
4.1 Introdução
A redução do tempo de transmissão (taxa de transmissão) e da quantidade do
espaço de armazenamento de dados são fatores importantes em qualquer técnica de
compressão. Portanto, surgiram vários métodos e algoritmos de compressão de
informação (dados) abordando esses dois aspectos, com o objetivo de representar a
informação de imagem por códigos mais eficientes sem redundância, de tal forma que a
informação original possa ser recuperada a partir desses códigos. Tais códigos
determinam a taxa de informação (bits), o tempo de transmissão e o espaço de
memória de armazenamento.
Uma técnica que utiliza esses métodos citados é a codificação aritmética (binária
ou não binária). A codificação aritmética é uma técnica de compressão baseada na
estatística das mensagens (pixels), ou seja, as probabilidades de ocorrência dos pixels
de uma fonte discretas. O método reduz a redundância entre os dados da imagem
original antes de entrarem num meio de transmissão ou armazenamento [3,4]. Por sua
vez ela proporciona flexibilidade no sentido de que o código para transmissão ou
Capítulo 4 - A Codificação Aritmética 40
armazenamento pode ser obtido durante o processo de codificação [5]. Além disso, a
codificação aritmética apresenta melhoria na taxa de compressão quando comparada
com a codificação de HUFFMAN [16,17].
A codificação aritmética é uma das famílias de códigos que compartilha a
propriedade de tratar uma seqüência de pixels como uma magnitude, sendo esta
codificação entrópica [18]. O procedimento de codificação é recursivo, isto é, realiza a
codificação ou a decodificação de uma amostra de dados em cada iteração repetindo-
se as mesmas operações.
O presente trabalho utiliza esses métodos de compressão, e aborda-se a técnica
de codificação aritmética binária adaptativa (CABA). Neste capítulo, discute-se a técnica
de codificação CABA, e também a codificação aritmética não binária para introduzir a
extensão de alfabetos. Alguns exemplos são usados para se ilustrar o algoritmo de
codificação e a diferença entre as duas técnicas.
4.2 A História da Codificação Aritmética
O primeiro trabalho em codificação aritmética foi feito por SHANNON em 1948
[8]. A idéia foi a de ordenar as mensagens segundo suas probabilidades de ocorrência.
Em seguida, enviam-se as probabilidades cumulativas de cada símbolo codificado em
fração binária e decodifica-se pela operação de comparação. Decorrido pouco tempo,
SHANNON e ELIAS conseguiram resolver o problema de precisão usando códigos de
comprimento fixo. Em 1972, surgiu a técnica de tipo LIFO (“Last In First Out”) por
SCHALKWIJK [19], isto é, o último pixel codificado é o primeiro decodificado.
RISSANEN descreveu a eficiência da técnica de codificação aritmética em que se evita
Capítulo 4 - A Codificação Aritmética
41
o código de bloco, e usou aproximações no projeto de código aritmético de LIFO [20].
PASCO descobriu a forma de código aritmético do tipo FIFO (“First In First Out”) [21],
ou seja, o primeiro pixel codificado é o primeiro decodificado. RISSANEN e LANGDON
[22] aproveitaram o código aritmético de FIFO para generalizar o conceito de
codificação aritmética para adotar outros tipos de códigos: códigos sem blocos, como
código de ELIAS [23,24]. Em anos seguintes, a derivada dos conceitos básicos de
técnica da codificação aritmética binária foi apresentada por RISSANEN, PASCO e
LANGDON. Essa técnica utiliza a estimação de probabilidade que deriva das
renormalizações de intervalo. O grupo do padrão JBIG aproveitou essa idéia e ela foi
adotada.
4.3 A Codificação Aritmética Binária Adaptativa (CABA)
A codificação aritmética é considerada como uma técnica poderosa comparada
com outras técnicas de compressão. Ela é também uma técnica de compressão exata,
isto é, os pixels recuperados são exatamente iguais aos pixels da imagem original. A
codificação CABA faz parte do padrão JBIG, onde o codificador CAA é a base principal
do padrão.
No padrão JBIG, o algoritmo de redução de resolução divide a imagem de
entrada em várias camadas de resolução. Para cada camada de resolução, o sub-bloco
do codificador aritmético adaptativo CAA recebe 3 fluxos de dados na entrada, a saber,
do pixel PIX a ser codificado, do que contem indicações sobre sua probabilidade
relativa oferecida pelo Modelo no valor de CX e do valor típico de predição VTP. O CAA
produz na saída somente um fluxo de dados definido como fluxo de palavra código (PC)
Capítulo 4 - A Codificação Aritmética 42
“code string” de acordo com o procedimento utilizado pelo codificador CAA. A Figura
(4.1) mostra as entradas e saída do CAA no modo progressivo. A codificação é feita
seqüencialmente pegando-se um pixel de cada fluxo de entrada. Ela permite a
compactação de seqüências binárias onde as estatísticas dessas mudam em uma base
bit-a-bit (na CABA um pixel é igual a um bit). O CAA declara para cada CX uma
estimativa de probabilidade condicional adaptativa (Pe) do pixel dado àquele contexto
utilizando-se o seu estimador de probabilidade interno [9]. O procedimento de CABA
baseia-se numa tabela de estimação de probabilidade [apêndice A2] fornecida pelo
padrão JBIG para estimar a probabilidade Pe relativa ao valor do pixel corrente que está
sendo codificado. Os pixels originais podem ser resgatados do fluxo de palavra código
PC com a técnica de FIFO.
$.@@B&A$
Codificador
Aritmético
Adaptativo
(CAA)
10001111101
10010110101
10111110001
PIX
CX PC
VTP
Fig. (4.1) � Entradas e saída do sub-bloco CAA.
4.4 O Mecanismo do Processamento do CAA
A técnica de codificação CABA não usa códigos prefixos, como é usado na
codificação de HUFFMAN [4]. Nessa codificação trata-se os pixels de entrada para CAA
Capítulo 4 - A Codificação Aritmética
43
como se tivessem dois níveis, isto é, cada pixel tem um valor binário “1” (preto) ou “0”
(branco). Portanto, dois conceitos principais considerados para essa técnica são:
• A palavra código “code point” do pixel é a probabilidade cumulativa (PC). Cada
palavra código é a soma das probabilidades relativas (PR) dos pixels
antecedentes [5];
• O algoritmo de CAA divide um intervalo da linha dos números reais entre “0” e “1”
correspondente às palavras código, ou seja, as probabilidades cumulativas dos
pixels são distribuídas dentro de um intervalo [0, 1), chamado intervalo
codificado corrente (IC). O colchete “[“ e o parênteses “)” indicam se o dígito
pertence ou não ao intervalo, respectivamente, conforme a Figura (4.2).
PR
PR
0.000
IC = 1.000
PC - Probabilidade Acumulativa (Palavra código)
Intervalo Codificado Corrente
(IC)
} Probabilidade Relativa
PC
Fig. (4.2) � Subdivisão do intervalo.
Como está ilustrado na Figura (4.2), o tamanho do sub-intervalo que está acima
de cada palavra código é equivalente à probabilidade relativa PR de ocorrência do
próprio pixel (também interpretado pelo CAA para a estimativa de probabilidade
condicional adaptativa Pe). Em outras palavras, o intervalo de cada pixel começa a
partir da sua palavra código e termina com o início do intervalo (palavra código) do pixel
seguinte.
Capítulo 4 - A Codificação Aritmética 44
4.4.1 O Processo de Codificação
No processo de codificação CABA, o fluxo de entrada PIX é mapeado para um
número real x dentro do intervalo IC. O fluxo de saída PC que vai ser transmitido ou
armazenado é a expansão binária do número x [24].
Durante o processo de codificação, o intervalo IC é dividido em dois sub-
intervalos com tamanhos proporcionais à probabilidade relativa PR de ocorrência dos
pixels. Os dois sub-intervalos são:
1. Sub-intervalo de pixel de maior ocorrência MPS (“More Probable Symbol”).
2. Sub-intervalo de pixel de menor ocorrência LPS (“Less Probable Symbol”).
O sub-intervalo LPS é colocado acima do sub-intervalo MPS e sempre com
tamanho menor. O algoritmo do codificador CAA usa o valor CX oferecido pelo sub-
bloco TM para estimar a probabilidade condicional Pe relativa ao valor do pixel corrente
a ser codificado usando-se a tabela de estimação de probabilidade do padrão JBIG
[Apêndice A2]. Em seguida mapeia cada pixel para um número real dentro do intervalo
IC. O intervalo que está associado ao valor do pixel a ser codificado é nomeado novo
intervalo codificado corrente (IN (.)). Essa operação é feita codificando-se um pixel
por iteração de maneira recursiva, isto é, o intervalo IN (.) é novamente dividido em dois
sub-intervalos e renomeado para intervalo IC, e assim por diante até que o algoritmo
codifique todos os pixels.
Para que o processo de codificação comece a operação, é necessário
especificar o intervalo do pixel que está sendo codificado. O codificador CAA mantém o
valor do tamanho do intervalo codificado corrente numa variável chamada IC e o valor
da sua base (palavra código) numa variável chamada CC, que seria o limite inferior do
Capítulo 4 - A Codificação Aritmética
45
intervalo IC. Para cada pixel a ser codificado, o codificador CAA utiliza essas duas
variáveis para determinar o novo intervalo IN (.) e sua base CN (.) usando-se as
seguintes equações:
IN (LPS) = IC * Pe ≈ Pe (4.1)
onde,
o valor Pe é tratado como sendo o tamanho do sub-intervalo LPS [25], tendo em
vista que o intervalo IC é normalizado para o valor um.
IN (MPS) = IC - IN (LPS) (4.2)
Para codificar o sub-intervalo LPS:
CN (LPS) = CC + IN (MPS) (4.3)
Para codificar o sub-intervalo MPS:
CN (MPS) = CC (4.4)
A Figura (4.3) mostra a subdivisão de um intervalo usando-se como exemplo
uma seqüência de pixels (fluxo PIX) a ser codificada dada por {0, 0, 1, 1}.
LPSI(1)C(1)
MPS
I(0)
C(0)
I(01) I(00)
I(001) I(000)
I(0011) I(0010)
PC
Base CC = 0.000
IC = 1.000
Fluxo PIX a ser codificado: 0 0 1 1
Intervalo Codificado Corrente
(IC)
Fig. (4.3) � Operação de subdivisão dos intervalos.
Capítulo 4 - A Codificação Aritmética 46
Tomando-se a Figura (4.3) como exemplo, o pixel a ser codificado no primeiro
intervalo é “0”, ou seja, o sub-intervalo MPS está sendo codificado. Aplicam-se as
equações (4.1), (4.2) e (4.4), e tem-se:
IN (LPS) = Pe = IN (1)
IN (MPS) = IC - IN (1) = IN (0)
CN (MPS) = CC = CN (0)
O segundo pixel a ser codificado é “0”, ou seja, o sub-intervalo MPS está sendo
codificado. Os resultados da primeira codificação serão usados para se realizar a
próxima codificação, ou seja, o processo de codificação será realizado recursivamente.
Portanto, a variável IN (MPS) é renomeada para IC e CN (MPS) é renomeada para CC.
Aplicam-se as equações (4.1), (4.2) e (4.4), obtendo-se:
IN (LPS) = Pe = IN (01)
IN (MPS) = IC - IN (01) = IN (00)
CN (MPS) = CC = CN (00)
Quando o codificador CAA termina o processo de codificação do fluxo PIX de
entrada, o fluxo de saída PC que vai ser transmitido ou armazenado será obtido pela
variável da base C (0011), ou melhor, o valor de C (0011) deve assumir algum valor
dentro do intervalo (0011).
Capítulo 4 - A Codificação Aritmética
47
4.5 A Decodificação Aritmética Binária Adaptativa (DABA)
O decodificador aritmético adaptativo (DAA) do padrão JBIG usa o mesmo
modelo usado no codificador CAA. O processo de decodificação é feito de maneira
recursiva por comparação de magnitude sendo que o sub-intervalo é apontado pela
palavra código PC [2]. Portanto, o fluxo PC no DAA é um ponteiro apontado para um
número real dentro do intervalo IC, relativo a sua base.
O sub-bloco do decodificador DAA recebe 3 fluxos de dados (PC, CX e VTP) na
entrada e produz o fluxo de pixels recuperados (PIX) na saída, como está mostrado na
Figura (4.4).
10001111101
Decodificador
Aritmético
Adaptativo
(DAA)
10010110101
10111110001
PIX CX
VTP
PC $.@@B&A$
Fig. (4.4) � Entradas e saída do sub-bloco DAA.
O procedimento de decodificação aritmética usa a palavra código e o tamanho
do intervalo do mesmo modo que o procedimento de codificação aritmética. Primeiro, o
limite do intervalo é identificado e em seguida pode-se determinar o pixel codificado.
Quando o procedimento de CAA codifica um intervalo (IC), o DAA faz questão de
determinar qual o sub-intervalo (IN (.)) que foi codificado, em outras palavras, qual o
sub-intervalo que está sendo apontado pelo fluxo PC de palavra código.
Capítulo 4 - A Codificação Aritmética 48
Durante o processamento, o algoritmo da DABA deve subtrair qualquer sub-
intervalo que foi somado ao fluxo PC pelo codificador CAA. Essa operação é efetuada
recursivamente para cada pixel a ser decodificado usando-se o processo de subdivisão
de intervalo que foi usado na codificação CABA. Isso significa que o decodificador DAA
desfaz o que foi feito pelo codificador CAA recursivamente.
4.6 A Codificação Aritmética Não Binária
O processo de codificação aritmética não binária utiliza a mesma estratégia
usada no processo de CABA. Ela não usa códigos prefixos, e o codificador recebe uma
seqüência de símbolos de entrada e suas indicações (probabilidades relativas) e
também mapeia a seqüência para um número real x dentro do intervalo IC.
Essa técnica aplica os mesmos dois conceitos principais usados na codificação
de CABA citadas na seção 4.4. Como foi dito anteriormente, a codificação aritmética
determina as palavras código durante o processo de codificação. Durante o
processamento, o algoritmo divide o intervalo IC em sub-intervalos correspondentes às
palavras código de símbolos de entrada. Portanto, as probabilidades cumulativas de
símbolos são distribuídas dentro do intervalo [0, 1), onde a probabilidade relativa de
ocorrência de cada símbolo é o tamanho do intervalo correspondente ao símbolo.
Para explicar o procedimento de codificação não binária, considere-se um
alfabeto de seqüência de quatro símbolos {a, b, c, d} como um exemplo. Suponha que a
Tabela (4.1) é usada para se consultar as probabilidades cumulativas PC calculadas
através das probabilidades relativas PR dos símbolos.
Capítulo 4 - A Codificação Aritmética
49
Tab. (4.1)- O alfabeto de símbolos para codificação aritmética.
Símbolo Probabilidade Relativa (PR)
Probabilidade Cumulativa (PC)
d 0.001 0.000
b 0.010 0.001
a 0.100 0.011
c 0.001 0.111
O codificador armazena o tamanho do intervalo na variável Ic e sua base na
variável CC. Portanto, para se determinar um novo intervalo (tamanho) IN (.) e sua
palavra código (base) CN (.), deve-se usar as seguintes equações:
IN (.) = IC * PR (4.5)
CN (.) = CC + (IC * PC) (4.6)
A Figura (4.5) mostra a distribuição das probabilidades cumulativas dentro de um
intervalo [0, 1).
d = 0.000
Intervalo Codificado Corrente
(IC)
b = 0.001
a = 0.011
c = 0.111
1.000
Fig. (4.5) � Distribuição das palavras código no intervalo IC.
Capítulo 4 - A Codificação Aritmética 50
Tome-se a seqüência de símbolos “a a d” a ser codificada como um exemplo. O
procedimento de codificação/decodificação pode ser efetuado usando-se as equações
(4.5) e (4.6), e resumido no seguinte com a ajuda da Figura (4.6):
CC = 0.000
Intervalo Codificado Corrente
(IC)
0.001
0.011
0.111
IC = 1.000
I (d)
I (b)
I (a)
I (c)
I (a)
I (d)
0.1101
0.1001
0.10011
0.1001
Símbolo a ser codificado: a a d
Fig. (4.6) � Subdivisão do intervalo para codificar a seqüência �a a d�.
1) O Processamento de Codificação
• Primeiro, o intervalo IC é dividido em sub-intervalos correspondentes à
probabilidade cumulativa de cada símbolo da cadeia de entrada. O valor inicial
do intervalo IC é “1.000” e da palavra código (sua base) CC é “0.000”. O primeiro
símbolo a ser codificado é “a”, então os novos valores são determinados da
seguinte forma:
Capítulo 4 - A Codificação Aritmética
51
CN (a) = CC + (IC * PC)
= 0.000 + (1.000 * 0.011) = 0.011
IN (a) = IC * PR
= 1.000 * 0.100 = 0.1000
Portanto, o símbolo tem palavra código “0.011” e intervalo [0.011, 0.111). Note-
se que o intervalo começa com o valor CN (a);
• Para codificar o segundo símbolo “a”, o valor do novo intervalo IN (a) será
transferido para o intervalo IC e a nova palavra código CN (a) será transferida
para a palavra código CC. O intervalo IC se divide usando-se o mesmo número de
subdivisões que foi usado para a divisão do intervalo original, ou seja, IC é
dividido em sub-intervalos relacionados às probabilidades cumulativas [6]. Os
valores do novo intervalo IN (a) e sua palavra código CN (a) são determinados da
seguinte forma:
CN (a) = CC + (IC * PC)
= 0.011 + (0.100 * 0.011) = 0.1001
IN (a) = IC * PR
= 0.100 * 0.100 = 0.010
Então, o símbolo “a” tem a palavra código “0.1001” e intervalo [0.1001, 0.1101);
• O terceiro e último símbolo que será codificado é “d”. A mesma conversão de
valores é feita, sendo que a operação recursiva para a codificação é:
CN (d) = CC + (IC * PC) = 0.1001 + (0.010 * 0.000) = 0.1001
Capítulo 4 - A Codificação Aritmética 52
IN (d) = IC * PR
= 0.010 * 0.001 = 0.00001
Agora, o símbolo “d” tem a palavra código “0.1001” e intervalo [0.1001, 0.10011). Então,
qualquer valor dentro o intervalo obtido (maior ou igual ao valor “0.1001” e menor do
que o valor “0.10011”) servirá para identificar o intervalo e representar o fluxo de saída
PC a ser transmitido ou armazenado como palavra código da seqüência de símbolos
original. Como está mostrado na Figura (4.6), a palavra código é tratada como uma
magnitude. Ela é uma fração binária que aponta para um número real dentro do
intervalo codificado corrente.
2) O Processamento de Decodificação
Deve-se agora explicar o procedimento de decodificação através da palavra
código obtida pela operação de codificação. A palavra código CC foi “0.1001011” e o
intervalo foi [0.1001, 0.10011). Usando-se a Tabela (4.1) para realizar o processo de
comparação do intervalo com o valor de probabilidade cumulativa PC de cada símbolo,
tem-se:
• O decodificador compara a palavra código “0.1001011” com os valores de
probabilidade cumulativa. Para se codificar o símbolo “b”, a cadeia de código
teria um valor dentro do intervalo [0.001, 0.011), evidentemente, o símbolo “b”
não é o primeiro símbolo que foi codificado. Para codificar o símbolo “a”, a cadeia
de código teria um valor pertencente ao intervalo [0.011, 0.111), portanto, esse
intervalo contem a palavra código “0.1001011”, ou seja, a palavra código ficaria
Capítulo 4 - A Codificação Aritmética
53
dentro do símbolo “a”. Isso indica que o símbolo “a” é que deve ser o primeiro
símbolo da seqüência de símbolos que foi codificada;
• O valor de probabilidade cumulativa PC do símbolo “a” é subtraída da palavra
código pelo decodificador, obtendo-se:
CC - PC = CN (a)
0.1001011 - 0.011 = 0.0011011
• No codificador, o segundo sub-intervalo foi ajustado multiplicando-se o mesmo
pelo valor 0.100 (probabilidade relativa). No outro lado, o decodificador desfaz
esse passo. O resultado da operação anterior é dividido pelo mesmo valor 0.100,
e tem-se:
CN (a) / PR = CDN
0.0011011 / 0.100 = 0.011011
onde,
CDN : a variável da base do novo sub-intervalo decodificado corrente.
A variável CDN é renomeada para a variável CC. De maneira recursiva, o
decodificador repete a mesma operação anterior para se obter o segundo símbolo que
foi codificado. Tem-se:
• Com a operação de comparação, a palavra código obtida “0.011011” ficaria
dentro do intervalo [0.011, 0.111), o qual pertence ao símbolo “a”. Portanto, o
Capítulo 4 - A Codificação Aritmética 54
símbolo “a” deve ser o segundo símbolo da seqüência de símbolos que foi
codificada;
• Subtraindo-se o valor de probabilidade cumulativa “0.011”, temos:
CC - PC = CN (a)
0.011011 - 0.011 = 0.000011
• Dividindo-se o resultado pelo valor da probabilidade relativa do símbolo “a”, tem-
se:
CN (a) / PR = CDN
0.000011 / 0.100 = 0.00011
Novamente a variável CDN é renomeada para a variável CC. Para se obter o
terceiro símbolo que foi codificado, basta reaplicar o primeiro passo. O decodificador
compara a palavra código obtida com os valores de probabilidade cumulativa PC.
Portanto, o terceiro símbolo que foi codificado é “d”.
4.7 Comentários
A codificação aritmética binária adaptativa CABA trabalha com uma seqüência
binária de dados, ou seja, a imagem de entrada do codificador aritmético binário é de 2
níveis. Ela é uma técnica de compressão sem perdas (exata). O codificador CAA
recebe o pixel a ser codificado, seu contexto e o valor típico. Em seguida, determina a
estimativa de probabilidade utilizando a tabela de estimação de probabilidade do
Capítulo 4 - A Codificação Aritmética
55
padrão JBIG. O mesmo contexto é usado tanto para o processo de codificação quanto
para o processo de decodificação. Devido ao fato de que o codificador recebe somente
valores binários (“1” e/ou “0”), o algoritmo mapeia o pixel que está sendo codificado
para um número real dentro do intervalo codificado corrente (IC), isto é, ele divide o
intervalo IC em dois sub-intervalos. Essa operação é feita recursivamente durante a
codificação. Os códigos são criados e transmitidos ou armazenados durante o processo
de codificação. O fluxo de palavra código PC criado pelo codificador CCA é a expansão
binária do número real dentro do intervalo IC que é gerado durante o processo de
codificação. O decodificador DAA desfaz o que foi feito pelo codificador CAA,
recursivamente.
Na codificação aritmética não binária, o intervalo IC é dividido em vários sub-
intervalos relacionados com as probabilidades cumulativas de símbolos da seqüência
de entrada. O codificador utiliza o mesmo procedimento usado na codificação aritmética
binária.
Capítulo 4 - A Codificação Aritmética 56
Capítulo 5 - As Rotinas de Implementação 57
Capítulo 5
AS ROTINAS DE IMPLEMENTAÇÃO
5.1 Introdução
As operações de codificação podem ser realizadas usando-se precisão fixa para um
número aritmético inteiro. Para realizar essas operações que são necessárias na fase
de implementação necessita-se de algumas ferramentas:
• Dois registradores: o registrador IC que contém o tamanho do intervalo IC
normalizado e o registrador C que contém a base do intervalo IC. A estrutura
dos registradores usada na implementação do CAA e do DAA é de 32 bits. As
Tabelas (5.1) e (5.2) mostram a estrutura para o codificador CAA e para o
decodificador DAA, respectivamente.
Tab. (5.1)- Estrutura de registradores do CAA.
Bits Registrador
MSB LSB
Ic 00000000 0000000T TTTTTTTT TTTTTTTT
C 0000cppp pppppsss bbbbbbbb bbbbbbbb
Capítulo 5 - As Rotinas de Implementação 58
Tab. (5.2)- Estrutura de registradores do DAA.
Bits Registrador
MSB LSB
IC 00000000 0000000T TTTTTTTT TTTTTTTT
CH ------------- ------------- bbbbbbbb bbbbbbbb
CL ------------- ------------- pppppppp 00000000
onde, CH, CL: juntos trabalham como se fossem um registrador de 32 bits;
c: bits de “carry”.
T: bits fracionais do valor de intervalo IC;
b: bits fracionais do valor de base do intervalo IC;
s: bits necessários para “carry - over” (espaço de bits);
p: bits fracionais de posições de dados que têm sido transformados do
registrador C;
• Um “buffer“ externo (BUF): para receber um byte de dados referentes aos bits
mais significados (MSB) do registrador C. Essa operação serve para impedir que
o “overflow” do registrador C aconteça durante o processamento. O BUF pode
ocupar uma área da memória ou um espaço do disco (um arquivo), onde são
armazenados os códigos de fluxo de saída PC. Portanto, o resultado final do
procedimento de CAA, correspondente à informação de uma imagem, que será
transmitida ou armazenada é o conteúdo do BUF;
Capítulo 5 - As Rotinas de Implementação 59
• Contador CT de deslocamento de bits: sua função básica é indicar quando um
byte do BUF está pronto para ser transmitido ou armazenado durante o processo
de codificação, ou quando um byte deve ser lido do fluxo PC durante o processo
de decodificação;
• Espaço de memória: usado como uma pilha apontada pelo contador SC,
sendo que nela a rotina armazena número de bytes de valor “0xff” até resolver o
problema de “carry - over”;
• A tabela de estimação de probabilidade: ela foi elaborada pelo padrão JBIG
para os estados de estimativa de probabilidade dos valores do fluxo CX
[Apêndice A2];
• A tabela de determinação do tom dos pixels: é usada pelo padrão JBIG para
se determinar os valores de pixels de camadas de baixa resolução [Apêndice
A1];
• A variável ST[CX] de um byte: os primeiros 7 bits são destinados para os
estados de estimativa de probabilidade dos valores do CX enquanto que o
último bit (MSB) é reservado para o valor de pixel (PIX) de maior ocorrência
sendo denominado VMPS[CX]. Essas variáveis são ajuntadas para se capturar a
estimativa de probabilidade adaptativa associada ao valor do CX particular.
Capítulo 5 - As Rotinas de Implementação 60
5.2 O Procedimento de CABA
Inicialmente, o algoritmo de CAA considera que os pixels com valor “0” (branco)
são de maior ocorrência do que os pixels com valor “1” (preto).
Como foi dito no capítulo 3, durante o processo de codificação CABA, o algoritmo
de CAA mapeia cada pixel oferecido pelo fluxo PIX para um número real dentro do
intervalo IC e gera os dois sub-intervalos (MPS e LPS). Esse número real é equivalente
à estimativa de probabilidade adaptativa do pixel oferecido. O novo intervalo IN (.) que
está sendo codificado pelo CAA é renomeado para o intervalo IC para recomeçar o
processo recursivo de codificação.
5.2.1 Determinação dos Intervalos
Uma aproximação aritmética simples é usada na subdivisão de intervalo. Para
um dado pixel, o procedimento de CAA determina o sub-intervalo LPS. É necessário
realizar uma multiplicação do intervalo IC com uma estimativa de probabilidade Pe do
sub-intervalo LPS como ilustrado na equação (5.1) [26].
IN (LPS) = Pe * IC (5.1)
Devido ao valor decimal do tamanho do intervalo IC, esse é sempre mantido
dentro da faixa [0x8000, 0x10000], a qual se aproxima do valor unidade. Sempre que o
tamanho fique inferior a “0x8000” é necessário renormalizá-lo. Então, a quantidade
armazenada em IN (LPS) é interpretada como sendo a probabilidade Pe. Assim, tem-se:
IN (LPS) ≈ Pe (5.2)
Capítulo 5 - As Rotinas de Implementação 61
O valor de IN (LPS) é um valor da tabela de estimativa de probabilidade
[Apêndice A2] relativo ao estado de estimação de probabilidade condicional adaptativa
do valor do CX particular (LSZ[ST[CX]]). Em outras palavras, sabe-se que o tamanho
do sub-intervalo LPS é equivalente à probabilidade Pe, portanto, tem-se:
LPS = Pe (5.3)
Após o procedimento de CAA que realiza a codificação do sub-intervalo MPS ou
do sub-intervalo LPS, um teste do valor do registrador IC é feito. Se o valor for inferior
ao limite “0x8000”, então é necessário renormalizá-lo até que ultrapasse o limite. Isso é
feito para que o valor do registrador IC fique dentro da faixa permitida. Enquanto isso, o
registrador C também é renormalizado.
Durante o processo de codificação, devido à aproximação feita no processo de
subdivisão do intervalo de probabilidade, pode acontecer que o tamanho do sub-
intervalo LPS seja maior do que o tamanho do sub-intervalo MPS. Para se evitar essa
inversão do tamanho, os dois sub-intervalos são trocados. Essa operação ocorre
quando uma renormalização é necessária. A troca de tamanho dos sub-intervalos é
denominada troca condicional (MPS/LPS).
Quando uma renormalização ocorre, solicita-se um processo de estimação de
probabilidade. Esse processo determina o novo estado de estimação de probabilidade
adaptativa do valor do CX atualmente codificado a fim de se codificar o próximo pixel.
Capítulo 5 - As Rotinas de Implementação 62
5.2.2 Rotinas e Fluxogramas de Codificação
Em cada plano de bits, o procedimento do CAA é executado para cada pixel do
fluxo PIX, cada valor correspondente de CX e cada valor típico de predição VTP. Três
rotinas principais utilizadas pelo procedimento de CAA são:
• A rotina INITC: usada para inicialização de operação, sendo que ela é chamada
quando se inicia o processo de codificação.
• A rotina CODIF: essa rotina é utilizada para a codificação dos dados da imagem
pixel-a-pixel, ou melhor, bit-a-bit.
• A rotina FIMC: é chamada quando o processo da codificação termina de codificar
os dados, sendo ela usada para se encerrar a operação de CAA.
A Figura (5.1) mostra o fluxograma do codificador CAA. Em todas as vezes, o
procedimento de CAA faz questão de testar se já foi atingido o fim dos dados dos
planos de bits. Se foi atingido, o procedimento passa para a rotina FIMC. Caso
contrário, segue para ler o próximo pixel do fluxo PIX a ser codificado, um novo
contexto CX e o valor típico de predição VTP. Em seguida, o algoritmo faz o teste de
valor do VTP. Os pixels que não sejam tipicamente previsíveis são codificados,
chamando-se a rotina CODIF.
1) A Rotina INITC
A função dessa rotina é colocar os valores iniciais em cada registrador bem
como em cada posição de memória.
Capítulo 5 - As Rotinas de Implementação 63
INITC
SIM
Ler PIX, CXe VTP
CODIF
NÃO
SIM
FIMC
NÃO Fim dosplanos
VTP étípico
PARE
Fig. (5.1)- Fluxograma do codificador CAA.
A seguir descrevem-se mais detalhes da função de cada rotina:
Uma exigência da ITU-T “International Telecommunication Union –
Telecommunication Standardization Sector” (antiga CCITT) é que toda página ou
documento deve começar com um pixel de valor branco “0”. Então, para todos os
valores possíveis do CX deve-se inicializar uma variável VMPS[CX] de um bit (o bit
MSB da variável ST[CX]) com o valor “0” a fim de se iniciar o processo de codificação,
Capítulo 5 - As Rotinas de Implementação 64
sendo que os estados de estimação de probabilidade são inicializados com o valor “0”
(os primeiros bits da variável ST[CX]).
O registrador IC é inicializado com o valor ‘0X10000”; o registrador C com o valor
“0”; o contador CT com o valor 11 (um byte de p e 3 bits de ss, conforme Tabela (5.1)) e
o contador de pilha SC com o valor “0”. A Figura (5.2) mostra o fluxograma da rotina
INITC.
Para todos os CX ST[CX] = 0
VMPS[CX] = 0
C = 0 IC = 0x10000
CT = 11 SC = 0
Fig. (5.2)- Fluxograma da rotina INITC.
2) A Rotina CODIF
Essa rotina tem como função verificar se o pixel corrente do fluxo PIX a ser
codificado é igual ou não ao valor de pixel de maior ocorrência VMPS[CX]. Nesse caso,
a verificação é feita todas as vezes que o CAA ler um pixel do fluxo PIX de entrada.
Caso sejam iguais, internamente, essa rotina solicita a chamada da rotina MPSCOD
para codificar o pixel de maior ocorrência. Caso contrário, a rotina prepara-se para
Capítulo 5 - As Rotinas de Implementação 65
executar a LPSCOD a fim de gerar o processo de CAA onde se codifica o pixel de
menor ocorrência. A Figura (5.3) mostra o fluxograma de rotina CODIF.
SIM
LPSCOD
NÃO PIX =
VMPS[CX]
MPSCOD
Fig. (5.3)- Fluxograma da rotina CODIF.
3) A Rotina MPSCOD
Basicamente, a função dessa rotina é codificar qualquer pixel com maior
ocorrência dentro do fluxo de dados binários PIX de entrada.
O processo começa realizando uma operação de redução de tamanho do
intervalo IC como ilustrado anteriormente na equação (3.2), produzindo-se o intervalo IN
(MPS). Se o valor do tamanho do intervalo IN (MPS) for superior ao limite “0x8000”,
nada acontece e a rotina é terminada. Caso o limite for inferior a “0x8000”, uma
verificação é feita para saber se o valor do intervalo IN (MPS) é menor do que o valor do
sub-intervalo LPS (LSZ[ST[CX]]). Caso isso seja verdade, uma troca condicional
(MPS/LPS) é feita e o sub-intervalo LPS será codificado em vez do sub-intervalo MPS.
A rotina calcula o valor da base CN (LPS) usando a equação (3.3) e o tamanho do sub-
intervalo IN (LPS) utilizando a equação (3.1). Após isso, a rotina determina o novo
Capítulo 5 - As Rotinas de Implementação 66
estado de estimativa de probabilidade do valor do CX particular relativo ao sub-intervalo
IN (MPS), utilizando a tabela de estimação de probabilidade [Apêndice A2], tanto para
esse caso quanto para o caso em que o intervalo IN (MPS) é maior do que LSZ[ST[CX]].
Finalmente, a rotina MPSCOD chama a rotina RENORMCOD para renormalizar os
registradores IC e C. A Figura (5.4) mostra o fluxograma da rotina MPSCOD.
SIM
IC = IC – LSZ[ST[CX]]
RENORMCOD
NÃO
SIM NÃO
IC < 0x8000
IC < LSZ
C = C + IC IC = LSZ[ST[CX]] ST[CX] = NMPS[ST[CX]]
Fig. (5.4)- Fluxograma da rotina MPSCOD.
Capítulo 5 - As Rotinas de Implementação 67
4) A Rotina LPSCOD
A função básica dessa rotina é codificar qualquer pixel com menor ocorrência do
fluxo PIX de entrada.
O início dessa rotina é semelhante ao da rotina MPSCOD para a determinação
do valor do sub-intervalo MPS. Em seguida, compara-se o intervalo IN (MPS) com o
sub-intervalo LPS. Caso o intervalo IN (MPS) seja maior, então o intervalo IN (MPS) é
somado com sua base CN (MPS) para produzir a base CN (LPS) do sub-intervalo LPS
conforme a equação (3.3).
O intervalo IN (LPS) é ajustado para o valor LSZ[ST[CX]] através da equação
(3.1). Após isso, tanto para esse caso quanto para o caso contrário (equivalente de
MPS/LPS), a rotina utiliza a tabela de estimação de probabilidade [Apêndice A2] para
verificar o valor do SWTCH[ST[CX]] do estado do valor do CX que está sendo
codificado. O SWTCH é um sinal de aviso indicando que o valor do pixel com maior
ocorrência tem mudado.
O pixel com maior ocorrência é o que está na variável VMPS[CX]). Se
SWTCH[ST[CX]] = 1, sendo que a rotina converte o valor “0” ( ou “1”) da variável
VMPS[CX] para o valor “1” (ou “0”), e fica sem fazer nada caso SWTCH[ST[CX]] = 0.
A rotina continua para consultar o novo estado de estimação de probabilidade do
valor de CX relativo ao sub-intervalo IN (LPS) utilizando-se a tabela de estimação de
probabilidade [Apêndice A2].
No passo seguinte, a rotina RENORMCOD é chamada. A Figura (5.5) mostra o
fluxograma da rotina LPSCOD.
Capítulo 5 - As Rotinas de Implementação 68
SIM
IC = IC – LSZ[ST[CX]]
RENORMCOD
NÃO
SIM NÃO
IC < LSZ
SWTCH = 1
C = C + IC IC = LSZ[ST[CX]]
VMPS[CX] =1 - VMPS[CX]ST[CX] = NLPS[ST[CX]]
Fig. (5.5)- Fluxograma da rotina LPSCOD.
5) A Rotina RENORMCOD
Essa rotina é chamada pelas rotinas MPSCOD e LPSCOD para renormalizar os
registradores IC e C. A rotina realiza um deslocamento do conteúdo dos registradores
para a esquerda. Enquanto o valor do registrador IC for inferior ao limite “0x8000”, a
rotina volta novamente para renormalizar os dois registradores. Durante esse tempo, o
conteúdo do contador CT é subtraído de um valor igual a “1”. Em seguida, a rotina faz
questão de testar o conteúdo de contador CT. Se for igual a “0”, a rotina BYTEOUT é
chamada para transmitir ou armazenar um byte de palavra código PC. O fluxograma da
rotina RENORMCOD está mostrado na Figura (5.6).
Capítulo 5 - As Rotinas de Implementação 69
NÃO
BYTEOUT
SIM
SIM
NÃO
CT = 0
IC < 0x8000
IC = IC << 1C = C << 1 CT = CT - 1
Fig. (5.6)- Fluxograma da rotina RENORMCOD.
6) A Rotina BYTEOUT
Essa rotina é chamada pela rotina RENORMCOD. Ela tem uma variável
temporária TEMP para armazenar um byte (no lado MSB) do registrador C (os bits de p,
conforme Tabela (5.1)) juntando-se o bit de “carry” (o bit de c na Tabela (5.1)) a fim de
se fazer o teste de “carry-over”.
O processo começa com o deslocamento do conteúdo do registrador C, 19 vezes
para a direita. O resultado é transferido para a variável TEMP. Em seguida, a rotina
testa o conteúdo de TEMP, ou seja, testa a ocorrência do “carry-over”. Existem três
casos para teste conforme estão descritos a seguir:
1. Se o conteúdo for maior do que o valor “0xff”, isso significa que há “carry-over”.
Esse “carry-over” deve ser somado com a saída recente de dados que está no
Capítulo 5 - As Rotinas de Implementação 70
BUF. Após isso, a rotina transmite ou armazena o conteúdo do BUF. Em
seguida, a rotina transmite o valor “0x00” SC vezes, em outras palavras,
transmite SC bytes de valor “0x00”. Assim, zera-se o conteúdo do contador SC.
No último passo, uma nova tentativa de dados de saída é determinada
colocando-se o conteúdo de TEMP no BUF sem nenhum “carry”;
2. Se o conteúdo for menor do que o valor “0xff”, isso significa que o problema do
“carry-over” está resolvido. A rotina transmite ou armazena o conteúdo de BUF.
Logo, em seguida, transmite o valor “0xff” SC vezes, e o conteúdo do contador
SC é zerado. O novo valor é armazenado no BUF e é igual ao valor de TEMP;
3. Se o conteúdo for igual ao valor “0xff”, não se transmite nenhum dado de saída e
o conteúdo do contador SC é incrementado de um valor igual a “1”.
Finalmente, após o procedimento de teste, a rotina ajusta o valor do registrador C. O
conteúdo será os fracionais do valor de base de intervalo IC (os bits de b, conforme
Tabela (5.1)) mais os bits de “carry-over” (os bits de s). O conteúdo do contador CT
é ajustado para o valor 8. A Figura (5.7) mostra o fluxograma da rotina BYTEOUT.
Capítulo 5 - As Rotinas de Implementação 71
SIM
TEMP = C >> 19
NÃO
SIM
NÃO
TEMP > 0xff
SC = SC + 1
Write BUF Write 0xff SC vezes
SC = 0 BUF = TEMP
TEMP = 0xff
C = C & 0x7ffffC T = 8
Write (BUF = BUF + 1) Write 0x00 SC vezes
SC = 0 BUF = TEMP & 0xff
BUF < 0
NÃO
BUF < 0
NÃO
SIM SIM
Fig. (5.7)- Fluxograma da rotina BYTEOUT.
7) A Rotina FIMC
Essa rotina internamente chama duas rotinas. A primeira é a rotina ZERARBITS
e a segunda é a rotina ESCREVFIM, como mostra a Figura (5.8).
ZERARAFIM
ESCREVFIM
Fig. (5.8)- Fluxograma da rotina FIMC.
Capítulo 5 - As Rotinas de Implementação 72
8) A Rotina ZERARBITS
O conteúdo do registrador C é ajustado para um valor dentro do intervalo [C, C +
IC – 1] com o maior número, de bits “0”, possível [6]. A Figura (5.9) mostra o fluxograma
dessa rotina.
SIM
TEMP = (IC – 1 + C)
NÃO TEMP < C
C = TEMP C = TEMP + 0x8000
TEMP = TEMP & 0xffff0000
Fig. (5.9)- Fluxograma da rotina ZERARBITS.
9) A Rotina ESCREVFIM
A função dessa rotina é resolver o problema de “carry-over”. É semelhante a
rotina BYTEOUT. A rotina testa a ocorrência do “carry-over”. Se ocorrer, um teste do
conteúdo do BUF é feito. Se o conteúdo for maior ou igual a “0”, envia-se o conteúdo do
BUF somado de um valor igual a “1” para a saída e em seguida, o valor “0x00” é
enviado SC vezes. Se não ocorrer “carry-over”, a rotina faz também um teste do
conteúdo do BUF. Se for maior ou igual a “0”, o conteúdo do BUF é enviado para a
saída e seguido pelo valor “0xff” SC vezes. Finalmente, 2 bytes do registrador C são
Capítulo 5 - As Rotinas de Implementação 73
transmitidos sendo que isso serve também se o conteúdo do BUF for menor do que “0”.
A Figura (5.10) mostra o fluxograma dessa rotina.
SIM
C = C << CT
NÃO
SIM NÃO
C > 0x7ffffff
BUF < 0
Write BUF + 1 Write 0x00 SC vezes
NÃO BUF < 0
Write BUF Write 0xff SC vezes
Write (C >> 19) & 0xffWrite (C >> 11) & 0xff
Fig. (5.10)- Fluxograma da rotina ESCREVFIM.
5.3 O Procedimento de DABA
Como foi dito anteriormente, a codificação é progressiva. Portanto, o processo de
decodificação ocorre de maneira inversa de modo a reverter o processo de codificação
a fim de se recuperar os dados originais. A decodificação é realizada construindo-se as
camadas de resolução de cada plano de bits uma por uma recursivamente. O algoritmo
de DAA utiliza os três fluxos como entrada: do pixel codificado PC, do contexto CX e do
valor típico de predição VTP.
Capítulo 5 - As Rotinas de Implementação 74
5.3.1 Rotinas e Fluxogramas de Decodificação
Para cada plano de bits, o procedimento do DAA é executado para cada pixel do
fluxo CX e cada valor típico de predição VTP, produzindo na saída o fluxo PIX dos
pixels recuperados de cada camada de resolução. O decodificador DAA internamente
contém duas rotinas: a rotina INITD para inicializar as variáveis e registradores
utilizados pelo decodificador DAA; e a rotina DECODIF para decodificar o fluxo PC, ou
seja, para recuperar os pixels originais do fluxo PIX. O fluxograma do decodificador
DAA está mostrado na Figura (5.11).
INITD
SIM
Ler CX e VTP
DECODIF
NÃO
SIM
NÃO Fim dosplanos
VTP étípico
Construir ascamadas
PARE
Fig. (5.11)- Fluxograma do decodificador DAA.
Capítulo 5 - As Rotinas de Implementação 75
O procedimento do DAA faz questão de testar se já foi atingido o fim do plano de
bits. Se não foi atingido, o procedimento continua a fim de ler o próximo contexto do
fluxo CX e um valor típico de predição VTP. Em seguida, chama-se a rotina DECODIF.
Caso contrário, as camadas de resolução são construídas.
Durante o processo de decodificação, o procedimento do decodificador DAA é
subtrair qualquer sub-intervalo que foi somado ao fluxo PC (registrador C) pelo
codificador CAA. O decodificador DAA usa somente o registrador CH para fazer a
comparação. Um byte do fluxo PC é inserido no MSB do registrador CL sempre que
necessário para dar continuidade ao processo de decodificação.
A seguir, descreve-se mais detalhes das funções de cada rotina:
1) A Rotina INITD
A função dessa rotina é a de inicialização. Para todos os valores possíveis do
CX, os estados de estimação de probabilidade, a variável VMPS[CX], o registrador C e
o contador CT são inicializados com o valor “0”; o registrador IC com valor “0x10000”.
Essa rotina internamente utiliza a rotina LERBYTE 3 vezes para ler os dados do
fluxo PC. Um byte por vez é lido e inicializa-se o conteúdo do contador CT com o valor
8. A Figura (5.12) mostra o fluxograma da rotina INITD.
Capítulo 5 - As Rotinas de Implementação 76
Para todos os CXST[CX] = 0
VMPS[CX] = 0CL = 0 e CT = 0
LERBYTE
CL = CL << 8
LERBYTE
LERBYTE
IC = 0x10000
CL = CL << 8
Fig. (5.12)- Fluxograma da rotina INITD.
2) A Rotina LERBYTE
A rotina testa se ainda existem dados do fluxo PC. Se não existem, o conteúdo
do BUF é ajustado para o valor “0”. Caso contrário, um byte do fluxo PC é inserido nos
oito bits superiores do registrador CL. Em seguida, o conteúdo do contador CT é
inicializado com o valor 8. A Figura (5.13) mostra o fluxograma dessa rotina.
Capítulo 5 - As Rotinas de Implementação 77
SIM NÃO Fim do
fluxo PC
BUF =1 byte do fluxo PC
C = C + (BUF << 8)CT = 8
BUF = 0
Fig. (5.13)- Fluxograma da rotina LERBYTE.
3) A Rotina DECODIF
A rotina começa determinando o sub-intervalo IN (MPS) para se fazer a
comparação com o conteúdo do registrador CH. Se o sub-intervalo IN (MPS) for maior,
um teste do sub-intervalo IN (MPS) é feito; se o tamanho do sub-intervalo for inferior ao
limite “0x8000”, o pixel recuperado é igual ao bit da variável VMPS[CX]. Caso contrário,
a rotina MPSDECOD é chamada. Se o sub-intervalo IN (MPS) for menor ou igual ao
conteúdo do registrador CH, a rotina LPSDECOD é chamada. Toda vez que a rotina
MPSDECOD ou LPSDECOD for solicitada, a rotina RENORMDEC é chamada. A Figura
(5.14) mostra o fluxograma da rotina DECODIF.
Capítulo 5 - As Rotinas de Implementação 78
NÃO
IC = IC – LSZ[ST[CX]]
RENORMCOD
SIM
SIM NÃO
CH < IC
IC < 0x8000
PIX = VMPS[CX]
LPSDECOD MPSDECOD
Fig. (5.14)- Fluxograma da rotina DECODIF.
4) A Rotina MPSDECOD
A Figura (5.15) mostra o fluxograma dessa rotina. A função básica é decodificar
o pixel com maior ocorrência. Se o sub-intervalo IN (MPS) for menor do que o sub-
intervalo IN (LPS), isso significa que o sub-intervalo IN (LPS) será decodificado, ou seja,
uma troca condicional (MPS/LPS) ocorrerá. O pixel recuperado seria o conteúdo da
variável VMPS[CX] convertido. O SWTCH[ST[CX]] do estado do valor do CX é testado.
Se o SWTCH[ST[CX]] = 1, o valor “0” (ou “1”) da variável VMPS [CX] é convertido para
o valor “1” (ou “0”). Se o SWTCH[ST[CX]] = 0, nada ocorrerá. A rotina consulta o novo
estado de estimação de probabilidade do valor do CX relativo ao sub-intervalo IN (LPS)
da tabela de estimação de probabilidade [Apêndice A2]. Caso o sub-intervalo IN (MPS)
Capítulo 5 - As Rotinas de Implementação 79
seja maior ou igual do que o sub-intervalo IN (LPS), então o sub-intervalo IN (MPS) será
decodificado. Ao mesmo tempo, a rotina determina o pixel recuperado e consulta-se o
novo estado de estimação de probabilidade do valor do CX relativo ao valor IN (MPS),
recorrendo-se à tabela de estimação de probabilidade [Apêndice A2].
SWTCH = 1
SIM NÃO
SIM
NÃO
IC < LSZ
PIX = VMPS[CX] ST[CX] = NMPS[ST[CX]]
VMPS[CX] =1 - VMPS[CX]
ST[CX] = NLPS[ST[CX]]
PIX = 1 – VMPS[CX]
Fig. (5.15)- Fluxograma da rotina MPSDECOD.
5) A Rotina LPSDECOD
A Figura (5.16) mostra o fluxograma dessa rotina. Basicamente, essa rotina
decodifica o pixel com menor ocorrência. Se por acaso o sub-intervalo IN (MPS) for
menor do que o sub-intervalo IN (LPS), uma troca condicional (MPS/LPS) ocorre e o
sub-intervalo IN (MPS) é decodificado. O conteúdo do registrador CH é subtraído do
conteúdo do registrador IC que foi somado pelo codificador CAA. O novo sub-intervalo
IN(LPS) é determinado. O pixel recuperado será o conteúdo da variável VMPS[CX]. Em
Capítulo 5 - As Rotinas de Implementação 80
seguida, o novo estado de estimação de probabilidade relativo ao sub-intervalo IN
(MPS) é consultado da tabela de estimação de probabilidade para o CX que está sendo
decodificado. Caso o sub-intervalo IN (MPS) seja maior ou igual do que o sub-intervalo
IN(LPS), o conteúdo do registrador CH é subtraído do conteúdo do registrador IC.
CH = CH - IC IC = LSZ[ST[CX]]
SWTCH = 1
SIM NÃO
SIM
NÃO
IC < LSZ
PIX = VMPS[CX] ST[CX] = NMPS[ST[CX]]
VMPS[CX] =1 - VMPS[CX]
ST[CX] = NLPS[ST[CX]]
PIX = 1 - VMPS[CX]
CH = CH - IC IC = LSZ[ST[CX]]
Fig. (5.16)- Fluxograma da rotina LPSDECOD.
O novo conteúdo do registrador IC é igual ao sub-intervalo IN (LPS) e o pixel
recuperado é calculado. O bit de SWTCH[ST[CX]] do estado do valor do CX é testado.
Se o SWTCH[ST[CX]] = 1, o valor da variável VMPS[CX] é convertido. Se o
SWTCH[ST[CX]] = 0, nada ocorrerá. Após isso, a rotina consulta na tabela de
Capítulo 5 - As Rotinas de Implementação 81
estimação de probabilidade [Apêndice A2] o novo estado de estimação de
probabilidade do valor do CX relativo ao sub-intervalo IN (LPS).
6) A Rotina RENORMDEC
Essa rotina é chamada pela rotina DECODIF toda vez que um pixel é recuperado
(decodificado).
O contador CT mantém o número de bits compactados no registrador CL.
Quando o conteúdo do contador CT for igual a “0”, um byte do fluxo PC é inserido no
lado superior (MSB) do registrador CL.
Durante o processo de decodificação, ambos os registradores IC e C (CH + CL)
são deslocados de um bit para a esquerda toda vez que o conteúdo do registrador IC
seja inferior ao limite “0x8000”.
Em seguida, um novo teste de contador CT é feito. Quando o conteúdo for igual
a “0”, um byte do fluxo PC é inserido no lado superior do registrador CL. O fluxograma
dessa rotina está mostrado na Figura (5.17).
Capítulo 5 - As Rotinas de Implementação 82
NÃO
SIM IC <
0x8000
IC = IC << 1C = C << 1 CT = CT - 1
CT = 0
LERBYTE
NÃO
SIM
CT = 0
LERBYTE
NÃO
SIM
Fig. (5.17)- Fluxograma da rotina RENORMDEC.
5.4 Comentários
Os fluxogramas das rotinas de codificação/decodificação facilitam a
compreensão da implementação dos blocos que compõem o padrão. Os dados da
imagem de entrada são colocados em uma área de memória e lidos byte a byte. Antes
de se iniciar o processo de codificação, a imagem de entrada é dividida em planos de
bits.
Capítulo 5 - As Rotinas de Implementação 83
As rotinas e os fluxogramas de codificação/decodificação mostram as operações
feitas em cada plano de bits. Em todas as vezes, o algoritmo testa se foi atingido o fim
dos dados do plano de bits. Se foi atingido, o procedimento passa a processar os dados
do próximo plano de bits.
O algoritmo utiliza a precisão fixa para se evitar o problema de “carry-over”, ou
seja, o tamanho do intervalo IC é sempre mantido dentro da faixa [08x000, 0x10000],
que se aproxima do valor unidade, através do processo de renormalização. Durante o
processamento, as operações de multiplicação e de divisão são realizadas pelo
deslocamento de bits.
Capítulo 5 - As Rotinas de Implementação 84
Capítulo 6 - Simulações e Resultados 85
Capítulo 6
SIMULAÇÕES E RESULTADOS
6.1 Introdução
Basicamente a codificação progressiva do padrão JBIG utiliza a técnica de
compressão CABA (Codificação Aritmética Binária Adaptativa) para imagens paradas
de 2 tons. Essa técnica é capaz de proporcionar altas taxas de compressão e permite o
modo de codificação sem perdas. Neste trabalho, a codificação com uma nova proposta
foi implementada para imagens paradas com escala de cinzas e imagens coloridas,
onde o processo de hierarquia (método progressivo) do codificador foi transferido para
o decodificador. Assim, pode-se construir as camadas de resolução depois de se
recuperar a imagem de cada plano de bits.
A avaliação do desempenho de um sistema em geral, pode ser realizada através
de simulações em computador. Tais simulações permitem testar ou avaliar o sistema
usando-se as imagens de teste como entrada, tirando-se proveito da rapidez e da
capacidade associadas aos computadores. Também é possível obter uma avaliação do
desempenho de um sistema de comunicações através do uso de aparelhos de testes
que medem os parâmetros que caracterizam tal sistema. No caso de desenvolvimento
de projetos, tais medidas objetivas são essenciais.
Capítulo 6 - Simulações e Resultados 86
Em geral, a vantagem das simulações em relação à implementação física
aparece quando se tem um número grande de opções que compartilham soluções para
a construção do sistema.
Apresenta-se neste capítulo as imagens de teste, seus formatos e a avaliação do
desempenho do algoritmo de codificação proposto, comparando-se com o algoritmo do
procedimento usual do padrão JBIG, tanto para as imagens com escala de cinzas,
quanto para as imagens coloridas. Também, mostram-se os resultados obtidos de
simulações de um caso especial da imagem com escala de cinzas, que utiliza o modo
seqüencial progressivo-único.
6.2 Imagens Fonte
As imagens fonte são usadas para ajudar no teste do sistema de codificação. As
imagens utilizadas pelo algoritmo CABA são imagens que possuem características
diferentes, sendo que esse fato permite avaliar e examinar a habilidade do sistema de
forma geral. São 8 imagens com escala de cinzas e 6 imagens coloridas com tamanhos
diferentes que foram usadas como entrada para o codificador CAA. Essas imagens são
padronizadas pelo SMPTE. As Figuras (6.1) e (6.2) mostram as imagens fonte, com
escala de cinzas e coloridas respectivamente.
A simulação da codificação é implementada com a ajuda de um computador PC com o
sistema operacional “Windows 2000 Profissional”. Aproveita-se a aplicação “Paint Shop
Pro” versão 6.0 para visualizar as imagens, sendo que os programas em software são
desenvolvidos em Linguagem C com aplicação “Borland C++” versão 5.
Capítulo 6 - Simulações e Resultados 87
a) Bars (512x512) b) Bird (256x256)
c) Cozinha (512x512) d) Sala (512x512)
Capítulo 6 - Simulações e Resultados 88
e) Clock (256x256) f) Cameraman (256x256)
g) Bridge (512x512) h) Karen (256x256)
Fig. (6.1)- Imagens com escala de cinzas.
Capítulo 6 - Simulações e Resultados 89
a) Jelly_beans1 (256x256) b) Couple (200x200)
c) Pássaro (768x512) d) Karen (200x200)
Capítulo 6 - Simulações e Resultados 90
e) Airplane (512x512) f) Lenna (200x 200)
Fig. (6.2)- Imagens coloridas.
6.3 Formato das Imagens Fonte
O tipo de formato do arquivo de imagem fonte é PGM (RAW) binário (“Portable
GreyMap - RAWBITS”) para a imagem com escala de cinzas, e PPM (RAW) binário
(“Portable PixMap - RAWBITS”) para a imagem colorida, ou seja, as amostras da
imagem são correspondentes aos dígitos binários (bits); então cada amostra ou pixel na
verdade representa 8 bits de valores “1`s” e/ou “0`s”.
Antes da imagem de entrada ser processada, ela é salva numa área de memória.
O algoritmo da CABA recebe somente imagens digitais binárias. Caso a imagem não
esteja na forma binária, é necessário utilizar um ambiente que faz a conversão para um
formato binário.
Capítulo 6 - Simulações e Resultados 91
Neste trabalho, utiliza-se o ambiente “Paint Shop Pro” versão 6.0 para converter
as imagens para o formato binário do tipo PGM ou PPM e conseqüentemente, as
imagens podem ser mostradas no monitor do computador. Esse formato é composto de
4 linhas no cabeçalho escritas no formato de texto (ASCII decimal). Em seguida, vêm os
dados da imagem que são escritos no formato RAW (binário) do tipo caracteres. Os
pixels são escritos em ordem (do Inglês “raster order”), ou seja, a varredura de leitura
começa com a primeira linha da esquerda para a direita, depois passa-se para a
segunda linha fazendo-se a leitura da mesma maneira e assim por diante. A estrutura
geral do arquivo da imagem PGM (RAW) tem as seguintes características [27,29]:
• Na primeira linha, tem-se a assinatura do arquivo de imagem, um número mágico
“magic number” para identificar o tipo de formato do arquivo, ou seja, a indicação
de que o arquivo é do tipo PGM. Esse número é composto por dois caracteres
iguais a “P5”;
• Na segunda linha, tem-se um comentário que começa com o símbolo “#”, e pode
ser ignorado;
• Na terceira linha, tem-se a informação sobre os números correspondentes à
largura e à altura dos pixels salvos no arquivo de imagem;
• Na quarta linha, tem-se o número da especificação dos valores de pixels, ou
seja, o máximo valor do nível de cinza que cada pixel da imagem pode carregar.
Em outras palavras, esse valor indica o número de bits por pixel;
• Nas linhas seguintes começam os dados (os pixels) ativos da imagem. Os pixels
estão em forma de caracteres, isto é, os pixels são concatenados em bytes, e
cada pixel tem 8 bits.
Capítulo 6 - Simulações e Resultados 92
A estrutura geral do arquivo de imagem PPM (RAW) é semelhante à estrutura do
arquivo PGM (RAW) com as seguintes diferenças [28,29]:
• Na primeira linha, o número mágico é “P6” ao invés de “P5”;
• Na quarta linha, tem-se o máximo valor do nível de cor que cada componente
possa carregar, ou seja, o máximo valor que um pixel possa carregar;
• Nos dados da imagem, cada amostra representa 3 bytes e cada byte representa
um componente de cor. O primeiro componente é a cor vermelha (R – “Red”), o
segundo é a cor verde (G – “Green”) e o terceiro componente é a cor azul (B –
“Blue”).
A Figura (6.3) mostra um exemplo do arquivo de imagem PGM (RAW) com o
máximo valor do nível de cinza igual a 255.
P5 # Created by Paint Shop Pro 6.0 256 256 255 4-)1)#3+&7-+:1-:1*5-'3+&/'&,""+!_) (%2)+! ˆ‰0+&1, $_.&"1)#4-+:10;3.;33;3.;33;33;52;3.:10;52;13;33;3.;:3- :1-6--4-+0+&/)$/'&0*'1)#1)#1,%1'%2)(/)$1,%2) (1)#3+ *3,'4-)/)$2)(4-)5-'70+5-'5-'4-)4-)5))/(',&$)!_)! % &1,%)
Fig. (6.3)- A estrutura da imagem com escala de cinzas com formato PGM.
Antes do algoritmo de codificação começar o processamento e iniciar a leitura
dos pixels da imagem, os pixels são armazenados em uma área de memória de tal
Capítulo 6 - Simulações e Resultados 93
modo que os pixels de cada linha tenham um número inteiro de bytes, (os pixels são
armazenados e tratados na forma de bits). Em outras palavras, se a largura da imagem
não for múltiplo inteiro de 8, então alguns bits com valores “0`s” devem ser inseridos no
fim de cada linha. A regra geral no procedimento da codificação CABA do padrão JBIG
consiste em: durante o processamento, em cada camada de resolução, o algoritmo
insere valores “0`s” nas bordas da imagem, ou seja, à esquerda, à direita e em cima,
sendo que a última linha é repetida para baixo.
Como um exemplo, a Figura (6.4) mostra uma imagem que representa a palavra
JBIG de 36 x 6 pixels. A sua representação na memória em forma binária é mostrada
na Figura (6.5), onde o bit “1” representa um ponto preto e o bit “0” representa um ponto
branco.
. . . . . x x x x . . x x x x x x . . . . x x x x . . . x x x x x x x . . . . . . . x x . . . x x . . . . x . . . . x x . . . x x . . . . . x . . . . . . x x . . . x x x x x x x . . . . x x . . . x x . . . . . . . . . . . . . x x . . . x x . . . . . x . . . x x . . . x x . . x x x x . . x . . . . x x . . . x x . . . . . x . . . x x . . . x x . . . . . x x . . x x x x x x . . . x x x x x x x . . . x x x x . . . x x x x x x x .
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
Fig. (6.4)- Imagem de 36x6 pixels de palavra JBIG.
0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0
0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 1
0 0 0 0 0 0 1 1 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 0
0 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 1 1
0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0
Fig. (6.5)- A representação da imagem JBIG na memória.
Note que, na figura da representação na memória, foi necessário inserir 5 bits de
valores “0`s” no fim de cada linha.
Capítulo 6 - Simulações e Resultados 94
6.4 Organização dos Dados Processados
Os dados da imagem de entrada, tanto para a imagem com escala de cinzas
quanto para a imagem colorida, são compostos de pixels. Cada pixel contém 8 bits.
Assim, o algoritmo do codificador CAA recebe somente seqüências de valores binários.
Seu processamento aplica-se em cada bit da seqüência binária de entrada, ou seja, o
algoritmo trabalha na base bit-a-bit. Logo, o codificador CAA recebe os dados da
imagem na forma de bits. A imagem de entrada é colocada numa área de memória e
tratada pelo algoritmo de CAA como sendo uma imagem de 2 tons (“bi-level image”).
Portanto, o codificador CAA processa os bits de cada pixel seqüencialmente.
6.4.1 Decomposição da Imagem Processada JBIG
A estrutura geral da Imagem de Entrada Processada (IEP) é dividida em duas
partes, como está mostrado na Tabela (6.1). A primeira parte contém a informação para
identificação dos dados processados (Cabeçalho da Imagem de Entrada - CIE), a qual
ajuda o decodificador DAA na recuperação da imagem processada; a segunda parte
contém os dados a serem transmitidos ou armazenados (Dados Processados da
Imagem de Entrada - DPIE).
Tab. (6.1)- Decomposição da estrutura de IEP.
IEP
DPIECIE
Capítulo 6 - Simulações e Resultados 95
Primeiramente, mostra-se a decomposição da estrutura usada no padrão JBIG, e
em seguida ilustra-se a decomposição da estrutura utilizada neste trabalho. A estrutura
de CIE do padrão JBIG para uma imagem de 2 tons é decomposta em vários campos
cujos tamanhos em byte são descritos nas últimas linhas. Isso é mostrado nas Tabelas
(6.2), (6.3) e (6.4).
Tab. (6.2)- Decomposição do CIE do padrão JBIG.
Fig. (6.7)- Decomposição de CIE do padrão JBIG. - X L M M Ordem O PD CIE - Cabeçalho
DL D PL D YD 0 X Y pções -Tabela
1 1 1 1 4 4 4 1 1 1 1 0 ou 1728
Tab. (6.3)- Decomposição do campo Ordem de CIE do padrão JBIG.
OrdemMSB
- SEQ ILEAVE SMID
1/8 1/8 1/8
HITOLO
1/81/8
- - -
LSB
1/8 1/8 1/8
Tab. (6.4)- Decomposição do campo Opções de CIE do padrão JBIG.
OpçõesMSB
-
1/8 1/8
PTDON
1/8
LRLTWO
LSB
1/8 1/8 1/8
VLENGTH PTBON
1/8
PDON PDPRIV PDULTI
1/8
Capítulo 6 - Simulações e Resultados 96
onde,
MX: valor máximo (“offset”) horizontal permitido para o pixel TA do template
adaptativo, com tamanho de 1 byte;
MY: valor máximo (“offset”) vertical permitido para o pixel TA do template
adaptativo, com tamanho de 1 byte;
LRLTWO: template de duas linhas na camada de menor resolução, de 1 bit;
VLENGTH: tamanho variável, essa variável é utilizada para a permissão de se
modificar a altura da imagem YD, de 1 bit;
PTDON: predição típica na camada diferencial, de 1 bit;
PTBON: predição típica na camada de menor resolução, de 1 bit;
PDON: habilitar a PD, de 1 bit;
PDPRIV: PD privado, para ativar a tabela PD privada, de 1 bit;
PDULTI: última PD, a tabela PD usada ultimamente, de 1 bit;
PD-TABELA: tabela PD, a tabela PD privada.
A estrutura de DPIE decomposta de um campo contém os dados da tira s da
camada de resolução d e do plano de bits p. Esse campo é chamado Dados da Tira
(DTs,d,p), e antes desse campo pode ter outro campo denominado Segmento de
Marcador “Marker Segment” (SM), como está mostrado na Tabela (6.5). Na verdade, o
SM é usado para controle de informação, e se for usado, é sempre colocado antes do
DTs,d,p e não pode ser colocado dentro do DTs,d,p.
Capítulo 6 - Simulações e Resultados 97
Tab. (6.5)- Decomposição do DPIE do padrão JBIG.
DPIE – Dados Processados
SM
variável
DTs,d,p
variável
SM DTs,d,p
variável variável
Cada DTs,d,p consiste de 3 campos internos. O primeiro contém os Dados
Codificados Protegidos (DCP). O segundo contém a variável Escapa (ESC) que é igual
ao valor “0xff”. O terceiro contém a variável DTNORM (Dados Terminados Normais)
com valor igual a “0x02” ou DTRST (Dados Terminados Reforçados) com valor igual a
“0x03”. Servem para identificar se o processo utilizou todos os dados da tira, se foi
encerrado normalmente ou se o encerramento do processo foi reforçado antes de
terminar os dados, respectivamente. A Tabela (6.6) mostra a estrutura do campo DTs,d,p.
Tab. (6.6)- Decomposição do campo de DTs,d,p.
variável
ESCDCP
DTs,d,p
1 1
DTNORM ou DTRST
Os dados de DCP são criados através da inserção do valor de STUFF que é
igual ao valor “0x00” após cada valor “0xff”, da variável ESC, encontrado na seqüência
dos Dados Codificados (DC).
A estrutura de CIE para uma imagem com escala de cinzas e uma imagem
colorida, usada neste trabalho, é mostrada na Tabela (6.7).
Capítulo 6 - Simulações e Resultados 98
Tab. (6.7)- Decomposição do CIE utilizado neste trabalho.
CIE - CabeçalhoDL D PL - XD YD Nível Liga Tipo Com
1 1 1 1 4 4 1 1 2 variável
PT
1
onde,
Tipo: o número mágico, com tamanho de 2 bytes;
Com: a linha de comentário, com tamanho variável de bytes;
Nível: valor máximo do nível de cada pixel, com tamanho de 1 byte;
Liga: tipo do template usado na camada de menor resolução (de duas ou de três
linhas), com tamanho de 1 byte.
PT: predição típica, com tamanho de 1 byte;
A decomposição da estrutura de DPIE é semelhante ao do padrão JBIG sem
perdas, usando-se o campo SM. Neste trabalho, devido ao fato de que a divisão em
tiras não é utilizada, o campo dos dados da tira DTs,d,p é substituído por um campo que
contém todos os dados das camadas de resolução em cada plano de bits denominado
Dados das Camadas (DCamd,p). A Tabela (6.8) mostra a decomposição utilizada neste
trabalho.
Capítulo 6 - Simulações e Resultados 99
Tab. (6.8)- Decomposição do DPIE utilizado nesse trabalho.
DPIE – Dados ProcessadosPLANO (7)
variável variável
PLANO (0)
DCamd,p
PLANO (6)
variável variável
FIMC
DCamd,p DCamd,p DCP
A estrutura de DCamd,p é igual àquela do campo DTs,d,p, conforme a Tabela (6.6).
Note que, na tabela (6.8) o último campo da variável FIMC (Final de Codificação)
contém somente os dados codificados protegidos DCP.
6.4.2 A Ordem da Leitura dos Dados de Entrada
Devido ao fato de que neste trabalho não foi usado o esquema de se dividir a
camada de resolução em tiras, a codificação foi implementada de tal forma que as
variáveis SEQ e SMID, citados no padrão JBIG para ordem dos dados, não foram
usadas. Entretanto, a simulação do algoritmo do codificador CAA faz o mesmo efeito de
que as variáveis HITOLO e ILEAVE tenham valores iguais a “0”. Conseqüentemente, o
procedimento de codificação começa processando os dados a partir da camada de
menor resolução indo para a de maior resolução. Em relação aos planos de bits, o
processamento inicia com os dados do maior plano de bits e concluindo com o menor
plano de bits. O modo de leitura dos pixels pelo algoritmo de codificação CABA é
seqüencial (“raster mode”), lendo-se da esquerda para a direita e de cima para baixo.
Capítulo 6 - Simulações e Resultados 100
Na simulação do programa de codificação, o campo de opções do CIE (Tabela
(6.3)) foi substituído por duas variáveis, escolhidas pelo usuário. Uma dessas variáveis
é a variável Liga que está no lugar da variável LRTWO, que define o tipo de template
modelo. O template de duas linhas é usado quando Liga = 2 e de três linhas é usado
quando Liga = 3. A outra variável é PT ao invés das duas variáveis PTDON e PTBON.
Quando PT = 1, então a predição típica é usada.
No procedimento de decodificação, o algoritmo de recuperação salva as
camadas de resolução de cada plano de bits num espaço de disco físico. Então, essas
camadas podem ser visualizadas pela aplicação “Paint Shop Pro” uma a uma.
6.5 Avaliação do Algoritmo de Codificação Progressiva
Para se verificar a aplicação e a análise do desempenho do algoritmo de
compressão CABA, a avaliação é feita utilizando-se as equações (1.1), (1.4) e (1.5). Os
resultados das simulações são mostrados em relação aos tamanhos das imagens
originais, aos tamanhos das imagens comprimidas, à taxa de bits, à taxa de
compressão e à porcentagem de compressão para cada imagem de entrada. Para cada
tipo de imagem (com escala de cinzas ou colorida), aplica-se o algoritmo de codificação
usual do padrão JBIG, e em seguida aplica-se o algoritmo da nova proposta.
6.5.1 Os Resultados das Imagens com Escala de Cinzas
Os resultados das simulações do algoritmo de codificação CABA correspondente
ao procedimento usual, ou seja, quando o sub-bloco “Redutor de Resolução” está no
codificador, são mostrados na Tabela (6.9).
Capítulo 6 - Simulações e Resultados 101
Tab. (6.9)- Resultados de simulações do procedimento usual do JBIG.
No. Imagem Fonte
TamanhoOriginal
(KB)
Tamanho Comprimido
(KB)
Fator de Compressão
Taxa de Bits (bits/pixel)
% Compressão
1 Bars 262,189 0,359 730,33 0,01 99,86 %
2 Bird 65,581 35,768 1,834 4,36 45,46 %
3 Cozinha 262,189 148,386 1,77 4,53 43,40 %
4 Sala 262,189 156,636 1,67 4,78 40,26 %
5 Clock 65,581 46,083 1,423 5,62 29,73 %
6 Cameraman 65,581 47,369 1,38 5,78 27,77 %
7 Bridge 262,189 204,563 1,282 6,24 21,98 %
8 Karen 65,581 52,570 1,25 6,41 19,84 %
Comentários da Tabela (6.9):
• Cada imagem de entrada foi dividida em 8 planos de bits, e cada plano foi
dividido em 3 camadas de resolução (D = 3);
• Todas as camadas de resolução dos planos de bits foram codificadas pelo
codificador aritmético adaptativo CAA e enviadas para o decodificador aritmético
adaptativo DAA;
• A opção de predição típica (PT) foi habilitada nas simulações da Tabela (6.9);
• A estrutura de Template Modelo escolhida nessas simulações para a menor
camada de resolução é de 3 linhas e apresenta melhores resultados do que
aquela de 2 linhas;
Capítulo 6 - Simulações e Resultados 102
• Observa-se um melhor desempenho do codificador à medida que se aumenta o
fator de compressão. Isso logicamente é razoável já que quanto maior for o fator
de compressão tanto maior será a porcentagem de compressão e menor será a
taxa de bits, (ou seja, pode-se representar cada pixel da imagem pelo valor da
taxa de bits que é menor do que aquela correspondente à representação por 8
bits da imagem original).
Os resultados das simulações do algoritmo da nova proposta são resumidos na
Tabela (6.10).
Tab. (6.10)- Resultados de simulações da nova proposta.
Taxa de Bits Fator de Tamanho No. Imagem Tamanho(bits/pixel) Fonte Original
(KB) Comprimido
(KB) Compressão
%
1 Bars 262,189 0,202 1297,97 0,006 99,92 %
2 Bird 65,581 29,621 2,214 3,61 54,83 %
3 Cozinha 262,189 122,072 2,15 3,72 53,44 %
4 Sala 262,189 129,866 2,02 3,96 50,47 %
5 Clock 65,581 38,638 1,697 4,71 41,08 %
6 Cameraman 65,581 38,908 1,69 4,75 40,67 %
7 Bridge 262,189 174,444 1,503 5,32 33,47 %
8 Karen 65,581 43,796 1,50 5,34 33,22 %
Compressão
Capítulo 6 - Simulações e Resultados 103
Comentários da Tabela (6.10):
• Nesse caso, o processo de redução de resolução foi transferido para o
decodificador aritmético adaptativo DAA;
• A imagem de entrada foi dividida em planos de bits, e cada plano foi codificado
com sua resolução total sem dividí-lo em camadas de resolução;
• Assim, somente os números de planos de bits (PL) e de camadas de resolução
desejadas (D) foram enviados para o decodificador DAA, a fim de se aplicar o
processo de redução de resolução no decodificador. Escolheu-se o número de
camadas de resolução igual a 3 (D = 3);
• A opção de predição típica (PT) foi habilitada nas simulações da Tabela (6.10);
• Nessas simulações, foi escolhida a estrutura de Template Modelo de 3 linhas
para as camadas de menor resolução;
• Pode-se notar que os resultados obtidos pela nova proposta na Tabela (6.10)
mostram uma melhora em relação aos resultados da Tabela (6.9). As
porcentagens de compressão da nova proposta são maiores. Logo, isso significa
que existe melhoria no desempenho do sistema proposto;
• Por exemplo, na codificação da imagem Karen(256x256) consegue-se alcançar
uma porcentagem de compressão de 13,38% maior do que aquela obtida na
codificação usual do padrão JBIG;
• Note também que a taxa de bits do processo proposto é menor do que aquela do
processo usual do padrão JBIG.
As imagens recuperadas correspondentes às camadas de resolução dos planos
de bits são mostradas na Figura (6.6).
Capítulo 6 - Simulações e Resultados 104
a) Bars: D2 D1 D0
b) Bird: D2 D1 D0
c) Cozinha: D2 D1 D0
Capítulo 6 - Simulações e Resultados 105
d) Sala: D2 D1 D0
e) Clock: D2 D1 D0
f) Cameraman: D2 D1 D0
Capítulo 6 - Simulações e Resultados 106
g) Bridge: D2 D1 D0
h) Karen: D2 D1 D0
Fig. (6.6)- As imagens recuperadas quando D = 3.
No caso do procedimento usual de codificação do JBIG, quando o sub-bloco
“Redutor de Resolução” está no lado de codificador, um caso especial é simulado com
a imagem em escala de cinzas, a qual é dividida em planos de bits e em camadas de
resolução. A camada de menor resolução é a única camada codificada e transmitida ou
armazenada, ou seja, a imagem codificada não é transmitida com seus detalhes totais.
Capítulo 6 - Simulações e Resultados 107
Nesse caso, os resultados das simulações são mostrados na Tabela (6.11) quando
cada plano de bits está sendo dividido em 3 camadas de resolução (D = 3).
Tab. (6.11)- Resultados de simulações do caso especial do JBIG.
No. Imagem Fonte
TamanhoOriginal
(KB)
Tamanho Comprimido
(KB)
Fator de Compressão
Taxa de Bits (bits/pixel)
% Compressão
1 Bars 262,189 0,178 1472,97 0,005 99,93 %
2 Bird 65,581 3,042 21,559 0,37 95,36 %
3 Cozinha 262,189 11,283 23,24 0,34 95,70 %
4 Sala 262,189 11,449 22,90 0,35 95,63 %
5 Clock 65,581 3,082 21,279 0,38 95,30 %
6 Cameraman 65,581 3,318 19,77 0,40 94,94 %
7 Bridge 262,189 13,538 19,367 0,413 94,84 %
8 Karen 65,581 3,492 18,78 0,43 94,68 %
Comentários da Tabela (6.11):
• Esse caso foi aplicado no processo usual do padrão JBIG, onde a imagem de
entrada foi dividida em 8 planos de bits e cada plano foi dividido em 3 camadas
de resolução (D = 3);
• Naturalmente, quando a imagem é dividida em camadas de resolução, cada
camada de baixa resolução conterá menos detalhes quando comparada com a
de alta resolução. Logo, a camada de menor resolução conterá menos
características em relação às outras. Portanto, o número de camadas de
resolução (D) deve ser escolhido de acordo com a aplicação desejada;
Capítulo 6 - Simulações e Resultados 108
• A opção de predição típica (PT) foi habilitada, e a estrutura de Template Modelo
escolhida nessas simulações para a menor camada de resolução é de 3 linhas;
• Pode-se notar que os resultados das simulações mostraram uma boa melhora no
desempenho do sistema, ou seja, as taxas de bits são muito baixas e as
porcentagens obtidas são muito altas. Por outro lado, a imagem tem uma perda
na qualidade como está visto na Figura (6.7).
As imagens recuperadas nesse caso são mostradas na Figura (6.7).
a) Bars (128x128) b) Bird (64x64)
c) Cozinha (128x128) d) Sala (128x128)
e) Clock (64x64) f) Cameraman (64x64)
Capítulo 6 - Simulações e Resultados 109
h) Karen (64x64) g) Bridge (128x128)
Fig. (6.7) - As imagens recuperadas de camadas de menor resolução (D = 3).
6.5.2 Os Resultados das Imagens Coloridas
Os resultados das simulações do algoritmo usual do padrão JBIG são mostrados
na Tabela (6.12) quando D = 3.
Tab. (6.12)- Resultados de simulações do algoritmo usual do JBIG.
No. Imagem Fonte
Tamanho Original
(KB)
Tamanho Comprimido
(KB)
Fator de Compressão
Taxa de Bits (bits/pixel)
% Compressão
1 Jelly_beans1 196,653 119,025 1,65 4,84 39,47 %
2 Couple 120,045 85,191 1,41 5,68 29,03 %
3 Pássaro 1179,693 886,768 1,33 6,01 24,83 %
4 Karen 120,045 94,068 1,28 6,27 21,64 %
5 Airplane 786,477 627,420 1,25 6,38 20,22 %
6 Lenna 120,045 99,131 1,21 6,61 17,42 %
Capítulo 6 - Simulações e Resultados 110
Para a nova proposta, os resultados das simulações do algoritmo implementado
são mostrados na Tabela (6.13).
Tab. (6.13)- Resultados de simulações da nova proposta (imagem colorida).
No. Imagem Fonte
Tamanho Original
(KB)
Tamanho Comprimido
(KB)
Fator de Compressão
Taxa de Bits (bits/pixel)
% Compressão
1 Jelly_beans1 196,653 100,462 1,96 4,09 48,91 %
2 Couple 120,045 70,617 1,70 4,71 41,17 %
3 Pássaro 1179,693 763,216 1,55 5,18 35,30 %
4 Karen 120,045 78,617 1,53 5,24 34,51 %
5 Airplane 786,477 536,491 1,47 5,46 31,79 %
6 Lenna 120,045 81,940 1,47 5,46 31,74 %
Comentários das Tabelas (6.12) e (6.13):
• A imagem colorida de entrada contem os 3 componentes (RGB) para cada
amostra. O algoritmo de codificação trata cada byte das amostras em separado
independentemente da sua posição.
• A imagem de entrada é dividida em 8 planos de bits, e cada plano foi dividido em
3 camadas de resolução (D = 3);
• Na Tabela (6.12), foi aplicado o algoritmo usual do JBIG, ou seja, todas as
camadas de resolução foram codificadas pelo codificador aritmético adaptativo
CAA e transmitidas ou armazenadas para serem decodificadas;
Capítulo 6 - Simulações e Resultados 111
• Na Tabela (6.13), foi aplicado o algoritmo proposto, ou seja, cada plano de bits
foi codificado com sua resolução total pelo codificador aritmético adaptativo CAA
sem dividí-lo em camadas de resolução, e transmitido ou armazenado para ser
decodificado;
• A opção de predição típica (PT) foi habilitada, e a estrutura de Template Modelo
(TM) de 3 linhas foi escolhida.
• Pode-se notar na Tabela (6.13), que os resultados obtidos para a nova proposta
mostram uma melhora em relação aos resultados da Tabela (6.12). As
porcentagens de compressão da nova proposta são maiores. Isso significa que
existe melhoria no desempenho do sistema proposto;
• Utilizando-se a nova proposta, e dependente da imagem de entrada, pode-se
alcançar uma porcentagem de compressão maior do que 14% em relação àquela
obtida pela codificação usual do padrão JBIG. Por exemplo, na imagem
Lenna(200x200), os resultados mostram uma porcentagem de compressão de
14,32% a mais;
• Pode-se notar que a taxa de bits do processo proposto é menor do que aquela
do processo usual do padrão JBIG. Portanto, a nova proposta mostrou melhor
desempenho também na taxa de compressão.
As imagens recuperadas com suas resoluções totais no caso da nova proposta
são mostradas na Figura (6.8).
Capítulo 6 - Simulações e Resultados 112
a) Jelly_beans1 (256x256)
d) Karen (200x200)
b) Couple (200x200)
c) Pássaro (768x512)
Capítulo 6 - Simulações e Resultados 113
f) Lenna (200x200) e) Airplane (512x512)
Fig. (6.8)- As imagens coloridas recuperadas na nova proposta.
Capítulo 6 - Simulações e Resultados 114
Capítulo 7 - Conclusões e Sugestões 115
Capítulo 7
CONCLUSÕES E SUGESTÕES
7.1 Conclusões
• O padrão JBIG é uma técnica de compressão de dados, com enfoque especial
direcionado à codificação aritmética binária adaptativa. O JBIG foi estabelecido
principalmente para codificação sem perdas de imagem em 2 níveis. Neste trabalho
analisa-se o padrão, sendo que ele apresenta como vantagem a possibilidade de
escolha da qualidade da imagem que está sendo codificada através do número das
camadas de resolução D.
• O método de codificação aritmética binária adaptativa é uma codificação entrópica
que utiliza a estatística dos pixels. A codificação aritmética é uma das famílias de
códigos que compartilha da propriedade de tratar uma cadeia de bits como uma
magnitude.
• Devido à flexibilidade da codificação aritmética, os códigos podem ser obtidos
durante o processo de codificação, enquanto em outras técnicas, tais como
Huffman, os códigos são obtidos antes do processo de codificação. A codificação
aritmética tem capacidade de receber pixels com distribuição estatísticas diferentes
e gerar os códigos que afetam diretamente as probabilidades, podendo assim
Capítulo 7 - Conclusões e Sugestões 116
adaptar os códigos de acordo com a mudança da estatística. Ela representa a
seqüência de pixels codificada com uma única palavra código.
• As equações (4.2) e (4.3) apresentam o problema de precisão que provoca a
propagação do “carry-over” dentro dos códigos. O algoritmo da codificação
aritmética binária adaptativa tem capacidade de usar uma precisão fixa para controle
do tamanho do código, limitando o crescimento dos dígitos nos códigos através do
processo de renormalização.
• O mecanismo de adaptação de codificação aritmética binária dedica-se à
determinação do novo estado de estimação de probabilidade Pe do contexto atual
para se codificar o próximo pixel.
• O estudo mostra que o padrão JBIG permite codificar primeiro a imagem de baixa
resolução e depois enriquecê-la com imagens de mais altas resoluções. Também se
permite ao usuário interromper o processo de codificação se desejado.
• O JBIG usa um método recursivo para implementação de códigos aritméticos para
compactação de dados, sem nenhuma multiplicação ou divisão, de forma a se obter
uma implementação de “hardware” fácil e rápida, o que é explicado no trabalho de
Kuang, Jou e Chen [25].
• A implementação do algoritmo de codificação aritmética binária adaptativa evita a
operação de multiplicação através do uso de deslocamento de bits. Tal fato faz com
que os valores dos registradores A e C (o tamanho e a base do intervalo) sejam
frações binárias. Isso permite o deslocamento para a esquerda dos bits contidos nos
registradores A e C.
Capítulo 7 - Conclusões e Sugestões 117
• A eficiência do método de compressão de dados usado refere-se à redução de
tamanho de dados transmitidos ou armazenados, à redução de custo e à diminuição
de tempo de transmissão.
• A estrutura do modelo e a estatística dos pixels (probabilidades relativas)
compartilham a eficiência da técnica de compressão. As simulações mostram que a
estrutura de 3 linhas oferecida pelo padrão JBIG dá melhor resultado do que aquela
de 2 linhas.
• A escolha do método de compressão é dependente das características e das
aplicações dos dados. A imagem que contem dados de características semelhantes
é boa candidata para compressão de dados, em outras palavras, nesse caso, a taxa
de compressão ou o fator de compressão é alto.
7.2 Contribuições
• Com a idéia de se dividir a imagem de entrada em vários planos de bits, e tratar
cada plano como se fosse uma imagem de 2 níveis, consegue-se implementar um
caso especial de codificação para a imagem de escala de cinzas, aplicando-se o
modo seqüencial progressivo-único com o objetivo de melhorar o desempenho do
sistema. Esse procedimento serve para algumas aplicações que não exigem a
reprodução de muitos detalhes na imagem de saída. A menor camada de resolução
em cada plano de bits é codificada e transmitida ou armazenada. Quando o número
de camadas de resolução (D) aumenta, isso resulta numa melhora da taxa de
compressão, pois a imagem terá menos detalhes, conforme a plataforma de
“software” apresentado no apêndice B.
Capítulo 7 - Conclusões e Sugestões 118
• Também, através do uso do método progressivo que faz parte do padrão JBIG,
implementou-se uma plataforma de “software” para imagem com escala de cinzas
usando-se o modo seqüencial compatível-progressivo como procedimento usual do
padrão JBIG. O número de camadas de resolução D e a habilitação do processo de
predição típica TP correspondem aos parâmetros que podem ser escolhidos como
opções de entrada pelo usuário.
• Neste trabalho, consegue-se alcançar uma melhoria na taxa de compressão
usando-se uma nova proposta que é comparada ao algoritmo de procedimento
usual do padrão JBIG. A proposta é transferir o sub-bloco Redutor de Resolução
(Hierarquia) do codificador para o decodificador, ou seja, o processo de redução de
resolução (modo progressivo) foi aplicado na decodificação ao invés de aplicá-lo na
codificação [Apêndice B]. Nesse caso, a divisão da imagem em camadas de
resolução é feita no decodificador. A imagem de entrada é dividida em 8 planos de
bits, pois tem-se 8 bits por pixel, portanto, cada bit representa um plano de bits.
• Testa-se também imagens coloridas. Cada amostra têm 3 bytes de 8 bits. O primeiro
byte corresponde ao componente vermelho R (“Red”), o segundo byte ao
componente verde G (“Green”) e o terceiro byte ao componente azul B (“Blue”).
Vários métodos podem ser usados para se trabalhar com as amostras desse tipo de
imagem. Nesta pesquisa, trabalha-se com bytes independentes das amostras, ou
seja, os componentes não são separados em matrizes distintas, mas são tratados
seqüencialmente nessa ordem: R, G e B. A largura da imagem colorida é
multiplicada por 3 e cada byte é dividido em 8 planos de bits independente da sua
Capítulo 7 - Conclusões e Sugestões 119
cor. A simulação em “software” foi implementada para o algoritmo de codificação do
procedimento usual do padrão JBIG.
• A presente proposta, também, foi aplicada em imagens coloridas e a plataforma de
“software” foi implementada [Apêndice B]. Consegue-se alcançar uma melhoria no
desempenho do sistema de codificação quando os resultados obtidos são
comparados com aqueles correspondentes ao algoritmo de procedimento usual do
padrão JBIG.
• A função do sub-bloco Predição Típica é a agilização do processo de codificação
mais do que a busca de alguma melhoria no desempenho. Durante a simulação,
executa-se os programas de codificação e avalia-se o efeito do processo de
predição típica. Tanto para as imagens com escala de cinzas quanto para as
imagens coloridas, o algoritmo de codificação não mostra nenhuma melhoria na taxa
de compressão, ou seja, a predição típica é usada somente para se agilizar o
processo de codificação.
• Implementou-se a plataforma de “software” usando-se a Linguagem C de
programação a fim de se realizar as simulações do algoritmo de codificação do
padrão JBIG. O objetivo foi o de testar e avaliar o desempenho da presente
proposta comparando-se os resultados com aqueles obtidos através do
procedimento usual do JBIG. Três plataformas estão no apêndice B, sendo elas:
1- A primeira para se realizar a codificação da menor camada de resolução
de imagem com escala de cinzas.
2- A segunda para se realizar a codificação com o método progressivo de
imagem com escala de cinzas com a nova proposta.
Capítulo 7 - Conclusões e Sugestões 120
3- A terceira para se realizar a codificação com o método progressivo de
imagem colorida com a nova proposta.
7.3 Sugestões
• Implementar os sub-blocos de Predição Determinística PD e Template Adaptativo
TA.
• Desenvolver a técnica de codificação do padrão JBIG para a codificação com
perdas.
• Utilizar juntamente com a codificação com perdas, uma filtragem para se alcançar
uma melhoria do desempenho.
• O padrão pode ser estendido com o intuito de se construírem técnicas mais amplas,
que possam ser aplicadas na transmissão digital de sinais de forma genérica. Por
exemplo, pode-se utilizar a codificação com o método progressivo do padrão JBIG
com e sem perdas para os sinais de Televisão Convencional e de Alta Definição.
• Pode-se projetar uma aplicação com uma base de dados que pode servir
dispositivos de saídas com capacidades de resolução diferentes, isto é, somente
aquela porção do arquivo da imagem compactada necessária para a reconstrução
(de acordo com a capacidade de resolução do dispositivo de saída particular) tem
que ser enviada e decodificada.
Apêndice A 121
Apêndice A1
Tabela para se determinar a Cor da Camada de Baixa Resolução
Índice Cor [0, 63] 00010001 01110011 11111111 11111111 00110011 11111111 11111111 11111111
[64, 127] 00000001 01110111 11111111 11111111 00110111 11111111 11111111 11111111 [128, 191] 00110111 11111111 11111111 11111111 01111101 11111111 11111111 11111111 [192, 255] 00110111 11111111 11111111 11111111 11111111 01111101 11111111 11111111 [256, 319] 00000001 00110111 11111101 11111111 00111111 11111111 11111111 11111111 [320, 383] 00110111 01111111 11111111 01111111 01111111 01111111 01111111 11111111 [384, 447] 00110101 11111111 11110111 11111111 11011111 01111111 11111111 11111111 [448, 511] 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [512, 575] 00000001 00100011 00000101 00111011 00010001 00100011 01110001 11111111 [576, 639] 00000001 01110101 00111011 01111111 00000000 01010011 11111110 11111111 [640, 703] 00000001 01000001 01111111 11111111 00001001 10110111 11111111 11111111 [704, 767] 00000000 01010011 01111111 11111011 10010011 01111001 11111111 11111111 [768, 831] 00000001 00000000 01110011 11111111 00110001 00010011 01110101 11111111 [832, 895] 00000000 01000001 10110111 11101110 00000001 00100001 11111100 11111111 [896, 959] 00000000 10010011 01110101 11111111 00010001 01101011 11110101 11111111
[960, 1023] 11101001 11110111 11111111 11111011 10110111 11111111 11111011 11111111 [1024, 1087] 00000001 00100011 00000001 00111111 00010001 00000001 01110111 11111111 [1088, 1151] 00000001 01110101 01101011 01111111 00000000 01010011 11111110 11111111 [1152, 1215] 00000001 01100001 01111111 11111111 00101001 00110111 11111111 11111111 [1216, 1279] 00000000 01110011 00111111 01111011 10010010 01111101 11111111 11111111 [1280, 1343] 00000001 00000000 01111011 11111110 00101111 00011011 01111111 11111111 [1344, 1407] 00000000 01000001 00110111 11111110 00001001 00110111 01111110 01111111 [1408, 1471] 00000000 11010010 01111111 11111111 00011011 01101111 11111111 11111111 [1472, 1535] 00000000 01110101 01111111 01110111 00100111 01111111 01111011 01111111 [1536, 1599] 00000001 00000011 00000001 00001001 00010001 00000001 01000001 10010011 [1600, 1663] 00000001 01110101 00100001 01010101 00000000 01010001 10000000 11110111 [1664, 1727] 00000001 01000001 01101011 00010011 00000001 00000000 11111011 11111111 [1728, 1791] 00000000 01010001 00000001 01110011 00000000 01000001 10110111 11111111 [1792, 1855] [1856, 1919]
00000001 00000000
00000000 01000000
01100001 00000001
10000001 01010110
00100111 00001000
00001001 00000000
00011110 00010000
10111111 01111111
[1920, 1983] 00000000 10000000 00100001 01110111 00000011 00000001 00111111 11111111 [1984, 2047] 01101000 11010000 11110011 10110011 00000000 11010011 11111011 11111111 [2048, 2111] 00000001 00000011 00110111 11111111 00110011 00110111 01111111 11111111 [2112, 2175] 00000001 01110111 01111111 11111111 00010001 01111011 11111111 11111111 [2176, 2239] 00000001 11110111 01111111 11111111 00111111 11111111 11111101 11111111 [2240, 2303] 00010010 11110111 11111111 11111111 11111111 11111101 11111111 01111111 [2304, 2367] 00000001 00010010 01111101 11111111 00111111 01111111 11111111 11111111 [2368, 2431] 00000000 01100010 11111111 01111111 00111111 00111111 01111111 11111111 [2432, 2495] 00010000 11111111 11110111 11111111 01111111 11111111 01111111 11111111 [2496, 2559] 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [2560, 2623] 00000001 00100011 00000001 00011011 00010001 00100011 01110111 11111111 [2624, 2687] 00000001 01110101 00101011 01110111 00000000 01000001 10111110 11111111 [2688, 2751] 00000001 11000001 01011011 01111111 00001001 00110011 01111101 11111111 [2752, 2815] 00000000 01010001 00110111 11111011 10101001 10110001 11111111 11111111 [2816, 2879] 00000001 00000000 01110001 10110111 00100001 00000011 01110101 11111111 [2880, 2943] 00000000 01000000 00010111 01101111 00000000 00000001 01111101 11111111 [2944, 3007] 00000000 11000001 01110101 11111111 00000001 10101011 01010001 11111111 [3008, 3071] 11101000 11010011 11111111 11111011 10111011 11111111 11111011 11111111 [3072, 3135] 00000001 00100011 00000001 00011011 00110001 00000001 01010011 01111111 [3136, 3199] 00000001 01110101 00101001 01111111 00000000 01010001 10110110 11111111 [3200, 3263] 00000001 11100000 01111011 11111111 00001010 00111011 01111111 11111111 [3264, 3327] 00000000 01110001 01111111 11111011 10001000 01110101 11111111 01111111 [3328, 3391] 00000001 00000000 01100001 11110110 00111111 00001001 01111111 11111111 [3392, 3455] 00000000 01000000 00010111 01111111 00001000 00010011 01111110 01111111 [3456, 3519] 00000000 10000000 01110111 11111111 00101011 00101111 01111111 01111111 [3520, 3583] 00000000 01110001 01111111 01110111 00101011 01111111 00111011 01111111 [3584, 3647] 00000001 00000011 00000001 00001001 00010001 00000001 01000001 00000001 [3648, 3711] 00000001 01110101 00100001 01010101 00000000 01010001 10000000 01010011 [3712, 3775] 00000001 01000001 01001001 00000001 00001001 00000000 00000001 00010011 [3776, 3839] 00000000 01010001 00000000 01010011 10000000 01000001 00010011 01111111 [3840, 3903] 00000001 00000000 01100001 10000000 00100001 00000001 00000001 00010011 [3904, 3967] 00000000 01000000 00000000 01000000 00000000 00000000 00000000 00010011 [3968, 4031] 00000000 10000000 00000000 00010011 00000001 00000001 01010001 01111111 [4032, 4095] 00000000 01010000 00000000 01110011 00000001 01010100 00110001 01110111
Apêndice A 122
Apêndice A2
Tabela de Estimação de Probabilidade
ST LSZ NMPS NLPS SWTCH ST LSZ NMPS NLPS SWTCH 0 0x5a1d 1 1 1 56 0x01f8 57 54 0 1 0x2586 2 14 0 57 0x01a4 58 55 0 2 0x1114 3 16 0 58 0x0160 59 56 0 3 0x080b 4 18 0 59 0x0125 60 57 0 4 0x03d8 5 20 0 60 0x00f6 61 58 0 5 0x01da 6 23 0 61 0x00cb 62 59 0 6 0x00e5 7 25 0 62 0x00ab 63 61 0 7 0x006f 8 28 0 63 0x008f 32 61 0 8 0x0036 9 30 0 64 0x5b12 65 65 1 9 0x001a 10 33 0 65 0x4d04 66 80 0 10 0x000d 11 35 0 66 0x412c 67 81 0 11 0x0006 12 9 0 67 0x37d8 68 82 0 12 0x0003 13 10 0 68 0x2fe8 69 83 0 13 0x0001 13 12 0 69 0x293c 70 84 0 14 0x5a7f 15 15 1 70 0x2379 71 86 0 15 0x3f25 16 36 0 71 0x1edf 72 87 0 16 0x2cf2 17 38 0 72 0x1aa9 73 87 0 17 0x207c 18 39 0 73 0x174e 74 72 0 18 0x17b9 19 40 0 74 0x1424 75 72 0 19 0x1182 20 42 0 75 0x119c 76 74 0 20 0x0cef 21 43 0 76 0x0f6b 77 74 0 21 0x09a1 22 45 0 77 0x0d51 78 75 0 22 0x072f 23 46 0 78 0x0bb6 79 77 0 23 0x055c 24 48 0 79 0x0a40 48 77 0 24 0x0406 25 49 0 80 0x5832 81 80 1 25 0x0303 26 51 0 81 0x4d1c 82 88 0 26 0x0240 27 52 0 82 0x438e 83 89 0 27 0x01b1 28 54 0 83 0x3bdd 84 90 0 28 0x0144 29 56 0 84 0x34ee 85 91 0 29 0x00f5 30 57 0 85 0x2eae 86 92 0 30 0x00b7 31 59 0 86 0x299a 87 93 0 31 0x008a 32 60 0 87 0x2516 71 86 0 32 0x0068 33 62 0 88 0x5570 89 88 1 33 0x004e 34 63 0 89 0x4ca9 90 95 0 34 0x003b 35 32 0 90 0x44d9 91 96 0 35 0x002c 9 33 0 91 0x3e22 92 97 0 36 0x5ae1 37 37 1 92 0x3824 93 99 0 37 0x484c 38 64 0 93 0x32b4 94 99 0 38 0x3a0d 39 65 0 94 0x2e17 86 93 0 39 0x2ef1 40 67 0 95 0x56a8 96 95 1 40 0x261f 41 68 0 96 0x4f46 97 101 0 41 0x1f33 42 69 0 97 0x47e5 98 102 0 42 0x19a8 43 70 0 98 0x41cf 99 103 0 43 0x1518 44 72 0 99 0x3c3d 100 104 0 44 0x1177 45 73 0 100 0x375e 93 99 0 45 0x0e74 46 74 0 101 0x5231 102 105 0 46 0x0bfb 47 75 0 102 0x4c0f 103 106 0 47 0x09f8 48 77 0 103 0x4639 104 107 0 48 0x0861 49 78 0 104 0x415e 99 103 0 49 0x0706 50 79 0 105 0x5627 106 105 1 50 0x05cd 51 48 0 106 0x50e7 107 108 0 51 0x04dc 52 50 0 107 0x4b85 103 109 0 52 0x040f 53 50 0 108 0x5597 109 110 0 53 0x0363 54 51 0 109 0x504f 107 111 0 54 0x02d4 55 52 0 110 0x5a10 111 110 1 55 0x025c 56 53 0 111 0x5522 109 112 0
112 0x59eb 111 112 1
Apêndice B 123
Apêndice B
1- Programas de codificação e decodificação da menor camada de resolução.
/* --- Utilizando imagem (escala de cinzas) de formato ROW tipo PGM codificando --- */ /* --- somente a menor camada de resolução para qualquer D de cada plano de bits --- */ /* -------------------- com a opção de usar o processo de Predição Típica --------------------- */ #include <ctype.h> #include <stdio.h> #include <assert.h> #include <stdlib.h> #include "tabela.h" #define ESC 0XFF #define STUFF 0X00 #define DTRST 0X03 #define DTNORM 0X02 #define PTB2CX 0X195 #define PTB3CX 0X0E5 /* ------ Descricao "status" de codificador aritmetico ----- */ struct code_estado { unsigned char ST[4096]; /* "status" de prob. dos contextos, e MSB = MPS */ unsigned int C; /* registrador C, base de intervalo codificado */ int A; /* registrador A tamanho normalizado de intervalo */ int SC; /* contador de pilha */ int CT; /* contador dislocamento de bits, determina quando * proximo byte vai ser armazenado ou transmitido */ int BUF; /* buffer para armazenar recente byte da saida != 0xff */ }; void BYTEOUT (int BUF, FILE *PCT) { putc (BUF, PCT); return; }; void FIMC (struct code_estado *s, FILE *PCT) { int TEMP; /** procura no intervalo codificado s->c com maior numeros de bits zero **/ if ((TEMP = (s->A - 1 + s->C) & 0xffff0000) < s->C) s->C = TEMP + 0x8000;
Apêndice B 124
else s->C = TEMP; /* --------- envia o resto de bytes para o arquivo de sai'da --------- */ s->C <<= s->CT; if (s->C > 0x7ffffff) { /* um overflow final vai acontecer */ if (s->BUF >= 0) { BYTEOUT (s->BUF + 1, PCT); if (s->BUF + 1 == ESC) BYTEOUT (STUFF, PCT); } if (s->C & 0x7fff800) for (; s->SC; --s->SC) BYTEOUT (0x00, PCT); } else { if (s->BUF >= 0) BYTEOUT (s->BUF, PCT); for (; s->SC; --s->SC) { BYTEOUT (0xff, PCT); BYTEOUT (STUFF, PCT); } } /* -------- envia os bytes finais somente se nao sao 0x00 -------- */ if (s->C & 0x7fff800) { BYTEOUT ((s->C >> 19) & 0xff, PCT); if (((s->C >> 19) & 0xff) == ESC) BYTEOUT (STUFF, PCT); if (s->C & 0x7f800) { BYTEOUT ((s->C >> 11) & 0xff, PCT); if (((s->C >> 11) & 0xff) == ESC) BYTEOUT (STUFF, PCT); } } return; } void CODIF (struct code_estado *s, unsigned int CX, unsigned int PIX, FILE *PCT) { int TEMP; register int lsz, ss; extern short LSZ[]; extern char NLPS[], NMPS[], SWTCH[]; assert (CX >= 0 && CX < 4096); /* determine ST[CX] */
Apêndice B 125
ss = s->ST[CX] & 0x7f; /* para capturar somente primeiros 7 bits */ assert (ss >= 0 && ss < 113); /* determine LSZ[ST[CX]] */ lsz = LSZ[ss]; if (((PIX << 7) ^ s->ST[CX]) & 0x80) /* PIX != MPS[CX] */ { /* ------ codifica o simbolo de menor ocorrencia LPS ------- */ if ((s->A -= lsz) >= lsz) /* se intervalo de MPS >= LPS */ { s->C += s->A; s->A = lsz; } if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* MSB ===> MPS[CX]=1-MPS[CX] * * XOR se A = B, entao A XOR @ B = 0 */ s->ST[CX] &= 0x80; /* mantem somente o valor de MPS=MSB */ s->ST[CX] |= NLPS[ss]; } else { /* ------- Codificar o simbolo de maior ocorrencia MPS ------ */ if ((s->A -= lsz) >= 0x8000) return; /*--- se A >= 0x8000, nao precisa renormalizacao ---*/ if (s->A < lsz) { s->C += s->A; s->A = lsz; } s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } do /* -------- renormalizacao de intervalo codificado --------- */ { s->A <<= 1; s->C <<= 1; --s->CT; if (s->CT == 0) /* outro byte pronto p/ envia-lo p/ arquivo da saida */ { TEMP = s->C >> 19; /* TEMP = um byte (com o carry) de reg. C */ if (TEMP > 0xff) /* ----- contiudo de BUF ----- */ { /* -------- ocorre overflow -------- */ if (s->BUF >= 0) { ++s->BUF; BYTEOUT (s->BUF, PCT); if (s->BUF == ESC) BYTEOUT (STUFF, PCT); } for (; s->SC; --s->SC) /* no final SC = 0 */ BYTEOUT (0x00, PCT); s->BUF = TEMP & 0xff;/*novo byte p/ enviar,talvez ocorrera overflow*/ assert (s->BUF != 0xff); }
Apêndice B 126
else if (TEMP == 0xff) /* talvez ocorrera overflow */ ++s->SC; else { /* nao ocorrera overflow */ if (s->BUF >= 0) BYTEOUT (s->BUF, PCT); for (; s->SC; --s->SC) /* no final SC = 0 */ { BYTEOUT (0xff, PCT); BYTEOUT (STUFF, PCT); } s->BUF = TEMP; /* buffer p/ novo byte enviado */ } s->C &= 0x7ffff; s->CT = 8; } } while (s->A < 0x8000); return; } void COD5 (struct code_estado *s, unsigned char *Res_bit, unsigned int largura, unsigned int altura, unsigned int alta_byte, unsigned int baixa_byte, unsigned int liga, unsigned int PT, FILE *PCT) { unsigned char *lp1, *lp2, *p1, *q1; unsigned int lpt, lpt_antiga, CX_CBR, SLNPT, PTDON, PTBON; unsigned int cx, PIX, i, j, fase1, fase2, baixa_altura, baixa_largura; unsigned int linha_h1,linha_h2,linha_h3,linha_l1,linha_l2,linha_l3; cx = 0; PIX = 0; lpt_antiga = 0; PTBON = PTDON = PT; baixa_altura = (altura +1)/2; baixa_largura = (largura +1)/2; lp2 = Res_bit; lp1 = lp2 + baixa_byte; for (i = 0; i < altura; i++) { /* ============ Predição Tipical Para Menor Camada ============ */ if (PTBON == 1) { p1 = lp2; if (i > 0) { q1 = lp2 - baixa_byte; while (q1 < lp2 && (lpt = (*p1++ == *q1++)) != 0); } else /* a primeira linha */ while (p1 < lp2 + baixa_byte && (lpt = (*p1++ == 0)) != 0); if (liga == 2) CX_CBR = 1;
Apêndice B 127
else CX_CBR = 0; SLNPT = !(lpt ^ lpt_antiga); CODIF (s, CX_CBR ? PTB2CX : PTB3CX, SLNPT, PCT); lpt_antiga = lpt; /** CX_CBR = PTB3CX caso CX_CBR = 0 **/ if (lpt) { /** Pular para próxima linha pois as duas linhas sao iquais **/ lp2 += baixa_byte; /** area solida **/ continue; /** vai ate o final do loop for (i= ....) **/ } } /* if PTBON */ linha_h1 = linha_h2 = linha_h3 = 0; if (i > 0) { linha_h2 = (unsigned int) *(lp2 - baixa_byte) << 8; if (i > 1 && liga == 3) linha_h3 = (unsigned int) *(lp2 - baixa_byte - baixa_byte) << 8; } for (j = 0; j < largura; lp2++) { linha_h1 |= *lp2; if ((j < (baixa_byte * 8 - 8)) && (i > 0)) { linha_h2 |= *(lp2 - baixa_byte + 1); if (i > 1 && liga == 3) linha_h3 |= *(lp2 - baixa_byte - baixa_byte + 1); } do { linha_h1 <<= 1; linha_h2 <<= 1; linha_h3 <<= 1; switch (liga) { case 2: cx = (((linha_h1 >> 9) & 0x00f) + ((linha_h2 >> 10) & 0x3f0)); break; case 3: cx = (((linha_h1 >> 9) & 0x003) + ((linha_h2 >> 12) & 0x07c) + ((linha_h3 >> 8) & 0x380)); break; default: fprintf (stderr,"Tipo de Template -%d- errado!\n" ,liga); exit(1); } PIX = ((linha_h1 >> 8) & 1); CODIF (s, cx, PIX, PCT); cx = 0; } while (++j & 7 && j < largura); } } /* i */ return; }
Apêndice B 128
unsigned char *reserva_char (unsigned int byte, unsigned int altura) /* -------- Reservando uma area com valores zeros nela -------- */ { unsigned int tamanho; unsigned char *ptr_p; tamanho = byte * altura; ptr_p = (unsigned char *) calloc(tamanho, sizeof(unsigned char)); if (!ptr_p) { fprintf (stderr, "Nao tem memoria suficiente para os pixels!\n"); exit(1); } return (ptr_p); } unsigned int TAMANHO (unsigned int largura) { unsigned int tamanho, MOD; /* --------- No. de pixels por linha ----------- */ MOD = largura % 8; if (MOD) tamanho = largura + (8 - MOD); else tamanho = largura; return (tamanho); } unsigned int TAM_IN_BYTE (unsigned int largura) { unsigned int byte, tamanho_largura; /* ------- No. de bytes por linha ------- */ tamanho_largura = TAMANHO (largura); byte = tamanho_largura / 8; return (byte); } unsigned int x[20]; void REDUZIR (unsigned char **bit, unsigned char *b, unsigned int D, unsigned int nova_lar, unsigned int altura) { extern char Map[]; unsigned char *Meio, *F, *Pr, *P_baixa; unsigned int cnt, chave, ca, i, j, Resultado, cont_a, cont_b; unsigned short linha_F, linha_Meio, linha_Pr, linha_baixa2, baixa_pix; unsigned int baixa_nova_lar, baixa_altura, alta_byte, baixa_byte, baixa_L_tamanho;
Apêndice B 129
cnt = 0; chave = 1; for (ca = 1; ca < D; ca++) { if (chave != 0) { x[cnt] = nova_lar; cnt += 1; x[cnt] = altura; alta_byte = TAM_IN_BYTE (nova_lar); bit[ca-1] = b; chave = 0; } Meio = bit[ca-1]; F = Meio - alta_byte; Pr = Meio + alta_byte; baixa_nova_lar = (nova_lar + 1)/2; baixa_altura = (altura + 1)/2; cnt += 1; x[cnt] = baixa_nova_lar; cnt += 1; x[cnt] = baixa_altura; baixa_L_tamanho = TAMANHO (baixa_nova_lar); baixa_byte = baixa_L_tamanho / 8; bit[ca] = reserva_char (baixa_byte, baixa_altura); P_baixa = bit[ca]; /* ---- Ponha-se os pixels da camada de baixa Resolucao a partir ---- */ /* ---- de mesma e de camada de alta Resolucao ----- */ for (i = 0; i < baixa_altura; i++) { if (2 * i + 1 >= altura) Pr = Meio; /* -- para repetir ultima linha da imagem no final -- */ baixa_pix = 0; linha_F = linha_Meio = linha_Pr = linha_baixa2 = 0; for (j = 0; j < baixa_L_tamanho; j += 8) { *P_baixa = 0; linha_baixa2 |= i ? *(P_baixa - baixa_byte) : 0; /* --- linha_baixa2 = 0 caso i=0, e caso contrario pega --- */ /* --- o byte que esta a cima do byte atual do P_baixa --- */ for (cont_b=0; cont_b < 8 && j+cont_b < baixa_nova_lar; cont_b += 4) { if (((j + cont_b) >> 2) < alta_byte) { /* --- p/ evitar passar o limite de bytes na alta Res. --- */ linha_F |= i ? *F : 0; ++F; linha_Meio |= *Meio; ++Meio; linha_Pr |= *Pr; ++Pr; } for(cont_a=0;cont_a<4 && j+cont_b+cont_a<baixa_nova_lar; cont_a++)
Apêndice B 130
{ linha_Pr <<= 2; linha_Meio <<= 2; linha_F <<= 2; linha_baixa2 <<= 1; Resultado = 0; Resultado = (((linha_Pr>>8) & 0x0007)+((linha_Meio>>5)& 0x0038) + ((linha_F >> 2) & 0x01c0) + (baixa_pix << 9) + ((linha_baixa2 << 2) & 0x0c00)); assert (Resultado >= 0 && Resultado < 4096); baixa_pix = 0; baixa_pix = Map[Resultado]; *P_baixa <<= 1; *P_baixa |= (unsigned char) baixa_pix; /** P_baixa e linha atual na baixa Res. **/ } /* --- baixa_pix e linha a cima do pixel ? estimado --- */ } ++P_baixa; } /* j */ /* ----- inserir bits de valores zeros no final de cada linha ----- */ /* ----- ate atengir ao tamanho de baixa_L_tamanho ----- */ *(P_baixa - 1) <<= baixa_L_tamanho - baixa_nova_lar;/** recua P_baixa */ F += alta_byte; /* para um byte ai colocand 0's nas digitos de byte */ Meio += alta_byte; Pr += alta_byte; /* pula 1 line p/ repetir o processo na 3 e 4 linha */ } /* i */ nova_lar = baixa_nova_lar; altura = baixa_altura; alta_byte = baixa_byte; } /* ca */ return; } void DIVIDE (struct code_estado *s, unsigned int nova_lar, unsigned int altura, unsigned int D, unsigned int liga, unsigned int PT, FILE *PCT, unsigned char *b) { unsigned int cnt; unsigned char **bit; unsigned int alta_byte, baixa_byte; bit = (unsigned char **) calloc(D, sizeof(unsigned char)); if (!bit) { fprintf (stderr, "Nao tem memoria suficiente para a reserva!\n"); exit(1); } if (D == 1) { alta_byte = TAM_IN_BYTE (nova_lar); COD5(s, b, nova_lar, altura, alta_byte, alta_byte, liga, PT, PCT); goto F; } /*** D ***/
Apêndice B 131
REDUZIR (bit, b, D, nova_lar, altura); cnt = (D*2)-1; altura = x[cnt]; cnt -= 1; nova_lar = x[cnt]; baixa_byte = TAM_IN_BYTE (x[D*2-2]); /* ---- Codificando somente a menor camada de Resolução ---- */ COD5 (s, bit[D-1], nova_lar, altura, baixa_byte, baixa_byte, liga, PT, PCT); F: BYTEOUT (ESC, PCT); BYTEOUT (DTNORM, PCT); free(bit); return; } void **PLANO_P (unsigned int largura, unsigned int altura, unsigned char *bit, unsigned char **g) { unsigned char *k; unsigned int i, j; unsigned char *b0, *b1, *b2, *b3, *b4, *b5, *b6, *b7; /* -------- Colocar os dados de cada bit de 8 bits -------- */ /* ------------- numa area de memoria separada ------------ */ b0 = g[0]; b1 = g[1]; b2 = g[2]; b3 = g[3]; b4 = g[4]; b5 = g[5]; b6 = g[6]; b7 = g[7]; k = bit; for (i = 0; i < altura; i++) { for (j = 0; j < largura; j++) { *b0 <<= 1; *b0 |= (*k & 0x01); *k >>= 1; *b1 <<= 1; *b1 |= (*k & 0x01); *k >>= 1; *b2 <<= 1; *b2 |= (*k & 0x01); *k >>= 1; *b3 <<= 1; *b3 |= (*k & 0x01); *k >>= 1; *b4 <<= 1; *b4 |= (*k & 0x01); *k >>= 1; *b5 <<= 1; *b5 |= (*k & 0x01); *k >>= 1; *b6 <<= 1; *b6 |= (*k & 0x01); *k >>= 1; *b7 <<= 1; *b7 |= (*k & 0x01); if ((j & 7) == 7) { b0++; b1++; b2++; b3++; b4++; b5++; b6++; b7++; } k++; } } /* i */ return; } void MEM_R (unsigned char *ptr, unsigned int altura, unsigned int largura, FILE *fpix, char *fe) { fread (ptr, largura * altura, sizeof(unsigned char), fpix); if (feof(fpix))
Apêndice B 132
{ fprintf (stderr, "Fim do arquivo de pixels '%s' inesperado !\n",fe); exit(1); } if (ferror(fpix) || fclose(fpix)) { fprintf (stderr,"Problema durante a leitura do arquivo '%s'\n",fe); exit(1); } return; } unsigned int lerint (FILE *fpix) { unsigned int i, c; if ((c = getc(fpix)) != EOF) { ungetc(c, fpix); fscanf(fpix,"%d",&i); } return i; } FILE *ABRIR (char *f, FILE *PCT) { FILE *fpix; unsigned int k; unsigned char L, tipo; fpix = fopen(f,"rb"); if (!fpix) { fprintf (stderr,"Nao pode abrir o arquivo de pixels '%s'\n",f); exit(1); } if ((L = getc(fpix)) != 'P') { fprintf (stderr,"O arquivo '%s' nao e tipo PGM !\n",f); exit(1); } fwrite (&L, 1, sizeof(unsigned char), PCT); if ((tipo = getc(fpix)) != '5') { fprintf (stderr,"O arquivo '%s' nao e com formato RAW de tipo PGM !\n",f); exit(1); } fwrite (&tipo, 1, sizeof(unsigned char), PCT); fprintf (PCT,"\n"); while ((k = getc(fpix)) != EOF && !isdigit(k)) if (k =='#') { ungetc(k, fpix);
Apêndice B 133
while ((k = getc(fpix)) != EOF && !(k == 13 || k == 10)) fprintf (PCT,"%c",k); fprintf (PCT,"\n"); } ungetc(k, fpix); return (fpix); } void CAMADAS (struct code_estado *s, char *fs, char *fe) { FILE *fpix, *PCT; unsigned char *area, **PLANO, h; unsigned int espaco, DL, D, NO_PLANO, liga, PT, m; unsigned int largura, altura, nivel, nova_lar, lar; unsigned char *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7; PCT = fopen(fs,"wb"); if (!PCT) { fprintf (stderr,"Nao pode abrir o arquivo '%s' de saida \n",fs); exit(1); } fpix = ABRIR (fe, PCT); printf ("\n\n =========>> ATENCAO! ... O numero de PLANOS = 8 \n\n"); NO_PLANO = 8; DL = 0; printf ("\n\n =====>> Digite 1 para ativar processo da Predição Tipical = "); scanf ("%d",&PT); C: printf ("\n\n ========>> Entre com numeros de Camadas de Resolucao = "); scanf ("%d",&D); if (D > 7 || D == 0) { printf ("\n O padrao JBIG ADEVERTE! o valor de camadas deveria ser \ de (1) a (7). ===> Por favor, repeta-se o processo ... \n\n"); goto C; } if (D == 1) printf("\n\n ATENCAO! .... A codificacao feita em cada PLANO somente\ para a camada com a resolucao total \n\n"); else printf("\n\n ATENCAO! .... A codificacao feita em cada PLANO somente\ para a menor camada de resolucao (D0) \n\n"); espaco = 0; largura = lerint (fpix); altura = lerint (fpix); h = getc(fpix); nivel = lerint (fpix); h = getc(fpix); /* ----- Colocar os dados da imagem original numa area ----- */ area = reserva_char (largura, altura); MEM_R (area, altura, largura, fpix, fe);
Apêndice B 134
/* ------- Reservar uma area para cada bit de 8 bits ------- */ /* ------------------ da imagem original ------------------- */ PLANO = (unsigned char **) calloc(NO_PLANO, sizeof(unsigned char)); if (!PLANO) { fprintf (stderr, "Nao tem memoria suficiente para a reserva!\n"); exit(1); } lar = largura / 8; /*-- largura nova para nova area de cada bit (PLANO) --*/ for (m = 0; m < NO_PLANO; m++) PLANO[m] = reserva_char (lar, altura); /* -------- Colocar os dados de cada bit de 8 bits -------- */ /* ------------- numa area de memoria separada ------------ */ t0 = PLANO[0]; t1 = PLANO[1]; t2 = PLANO[2]; t3 = PLANO[3]; t4 = PLANO[4]; t5 = PLANO[5]; t6 = PLANO[6]; t7 = PLANO[7]; PLANO_P (largura, altura, area, PLANO); free (area); fprintf (PCT,"%d", DL); fprintf (PCT,"%d", D); fprintf (PCT,"%d", NO_PLANO); fprintf (PCT,"%d", espaco); fprintf (PCT," %d %d ", largura, altura); fprintf (PCT,"%d ", nivel); printf ("\n Modelo Template de Baixa Res. : - Duas linhas => digite 2:"); printf ("\n - Tres linhas => digite 3:"); scanf ("%d",&liga); fprintf(PCT,"%d",liga); fprintf (PCT,"%d", PT); nova_lar = lar * 8; /* -- # de bits por linha em cada PLANO = largura -- */ DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t0); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t1); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t2); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t3); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t4); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t5); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t6); DIVIDE (s, nova_lar, altura, D, liga, PT, PCT, t7); FIMC (s, PCT); free(PLANO); if (ferror(PCT) || fclose(PCT)) { fprintf (stderr,"Problema durante escrever no arquivo '%s'\n",fs); exit(1); } return; } void INITC (struct code_estado *s) { int i;
Apêndice B 135
for (i = 0; i < 4096; s->ST[i++] = 0); s->C = 0; s->A = 0x10000; s->SC = 0; s->CT = 11; s->BUF = -1; /* buffer vazio */ return; } main (argc, argv) char *argv[]; { struct code_estado s; char *fe = argv[1], *fs = argv[2]; if ((fe != NULL) && (fs != NULL)) { INITC (&s); CAMADAS (&s, fs, fe); printf (" \n\n ...... FIM DO PROCESSO DE CODIFICACAO ......\n\n"); } else printf ("'erro'! \n\n Por favor, entre com: nome do arquivo tipo PGM \ e da saida para armazenar os dados compactados, sequencialmente.\n"); } /* main */
Apêndice B 136
/* --- Utilizando imagem (escala de cinzas) de formato ROW tipo PGM decodificando --- */ /* --------------- somente a menor camada de resolução de cada plano de bits ---------------- */ /* --------------------- com a opção de usar o processo de Predição Típica ---------------------- */ #include <stdio.h> #include <ctype.h> #include <assert.h> #include <stdlib.h> #include "tabela.h" #define ESC 0XFF #define STUFF 0X00 #define DTRST 0X03 #define DTNORM 0X02 #define PTB2CX 0X195 #define PTB3CX 0X0E5 unsigned int passa = 9; /* ------ Descricao "status" de decodificador aritmetico ----- */ struct decode_estado { unsigned char ST[4096]; /* "status" prob. dos contextos, e MSB = MPS */ unsigned int C; /* registrador C, base de intervalo a ser codificado*/ int A; /* registrador A, tamanho normalizado de intervalo */ int CT; /* contador de dislocamento de bits, determina * * quando pro'ximo byte vai ser lido */ int lnpt; /* flag de PT: linha nao e' Predicao Tipical */ int pseudo; /* flag de PTBON/PTDON: proximo pixel e' pseudo */ }; void LERBYTE (struct decode_estado *s, FILE *PCT) { unsigned int k; L: if ((k = getc(PCT)) != EOF) { if (k == ESC) { if ((k = getc(PCT)) == EOF) { printf ("\n Erro! No codigo do Encerramento surgeu 0xff extra!\n"); exit(1); } else if (k == DTNORM) goto L; else if (k == DTRST)
Apêndice B 137
{ printf ("\n O encerramento reforcado \n"); passa = getc(PCT); /*Em qual camada foi encerrado o chave,(D-ca)*/ goto L; /* --- passa = No. da camada onde foi o encerramento --- */ } else if (k == STUFF) k = 0xff; else { printf ("\n Erro! Nao ha codigo de STUFF \n\n"); exit(1); } } } else k = 0; s->C |= k << 8; s->CT = 8; return; } void RENORMDEC (struct decode_estado *s, FILE *PCT) { do { if (s->CT == 0) LERBYTE (s, PCT); s->C <<= 1; s->A <<= 1; --s->CT; } while (s->A < 0x8000); if (s->CT == 0) LERBYTE (s, PCT); return; } unsigned int DECODIF (struct decode_estado *s, FILE *PCT, unsigned short CX) { unsigned int PIX; extern short LSZ[]; register int lsz, ss; extern char NMPS[], NLPS[], SWTCH[]; ss = s->ST[CX] & 0x7f; /* determina o estado do contexto CX */ assert (ss < 113); lsz = LSZ[ss]; /* consulta a estimativa de probabilidade */ /* relativa ao estado do CX */ if ((s->C >> 16) < (s->A -= lsz)) if (s->A >= 0x8000) { PIX = s->ST[CX] >> 7; return PIX;
Apêndice B 138
} else /* ----------- MPSDECODIF ----------- */ if (s->A < lsz) { PIX = 1 - (s->ST[CX] >> 7); /* --- teste se a troca condicional (MPS/LPS) e' necessa ria --- */ if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* XOR para invertir o valor de MVAL[CX] */ /* - escolha o proximo estado de estimativa de probabilidade - */ s->ST[CX] &= 0x80; s->ST[CX] |= NLPS[ss]; } else { PIX = s->ST[CX] >> 7; s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } else /* ----------- LPSDECODIF ----------- */ if (s->A < lsz) { s->C -= s->A << 16; s->A = lsz; PIX = s->ST[CX] >> 7; s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } else { s->C -= s->A << 16; s->A = lsz; PIX = 1 - (s->ST[CX] >> 7); /* --- teste se a troca condicional (MPS/LPS) e necessaria --- */ if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* XOR para invertir o valor de MVAL[CX] * * se A = B; entao A XOR B = 0 */ /* - escolha o proximo estado de estimativa de probabilidade - */ s->ST[CX] &= 0x80; s->ST[CX] |= NLPS[ss]; } RENORMDEC (s, PCT); return PIX; } void DCOD5 (struct decode_estado *s, unsigned char *Res_bit, unsigned int largura, unsigned int altura, unsigned int alta_byte, unsigned int baixa_byte, unsigned int liga, unsigned int PT, FILE *PCT)
Apêndice B 139
{ unsigned char *lp1, *lp2, *p1, *q1; unsigned int i, j, CX_CBR, SLNPT, PTBON, PTDON; unsigned int cx, PIX, fase1, fase2, baixa_altura; register unsigned int linha_h1,linha_h2,linha_h3,linha_l1,linha_l2,linha_l3; cx = 0; PIX = 0; s->lnpt = 1; PTBON = PTDON = PT; baixa_altura = (altura +1)/2; lp2 = Res_bit; lp1 = lp2 + baixa_byte; for (i = 0; i < altura; i++) { /* =============== Predição Tipical =============== */ if (PTBON == 1) { if (liga == 2) CX_CBR = 1; else CX_CBR = 0; SLNPT = DECODIF (s, PCT, CX_CBR ? PTB2CX : PTB3CX); s->lnpt = !(SLNPT ^ s->lnpt); /** se A=B entao A.XOR.B=0 **/ if (!s->lnpt) { /* linha tipical (iqual a linha em cima dela) */ p1 = lp2; if (i == 0) while (p1 < lp2 + baixa_byte) *p1++ = 0; else { q1 = lp2 - baixa_byte; while (q1 < lp2) *p1++ = *q1++; } /* else */ lp2 += baixa_byte; continue; } /* if */ } /* if PTBON */ linha_h1 = linha_h2 = linha_h3 = 0; if (i > 0) { linha_h2 = (unsigned int) *(lp2 - baixa_byte) << 8; if (i > 1 && liga == 3) linha_h3 = (unsigned int) *(lp2 - baixa_byte - baixa_byte) << 8; } for (j = 0; j < largura;) { if ((j & 7) == 0) if ((j < (baixa_byte * 8 - 8)) && (i > 0)) { linha_h2 |= *(lp2 - baixa_byte + 1);
Apêndice B 140
if (i > 1 && liga == 3) linha_h3 |= *(lp2 - baixa_byte - baixa_byte + 1); } do { switch (liga) { case 2: cx = (linha_h1 & 0x00f) + ((linha_h2 >> 9) & 0x3f0); break; case 3: cx = (linha_h1 & 0x003) + ((linha_h2 >> 11) & 0x07c) + ((linha_h3 >> 7) & 0x380); linha_h3 <<= 1; break; default: fprintf (stderr,"Tipo de Template -%d- errado!\n" ,liga); exit(1); } PIX = DECODIF (s, PCT, cx); cx = 0; linha_h1 <<= 1; linha_h1 |= (PIX & 1); linha_h2 <<= 1; } while (++j & 7 && j < largura); *lp2 = linha_h1; lp2++; } /* j */ *(lp2 - 1) <<= baixa_byte * 8 - largura; } /* i */ return; } void MEM_W (unsigned char *bit, unsigned int altura, unsigned int alta_byte, FILE *pix_final, char fn[]) { fwrite (bit, alta_byte * altura, sizeof(unsigned char), pix_final); if (ferror(pix_final) || fclose(pix_final)) { fprintf (stderr,"Problema no escrito dos pixels em '%s'\n",fn); exit(1); } return; } unsigned char *reserva_char (unsigned int byte, unsigned int altura) /* -------- Reservando uma area com valores zeros nela -------- */ { unsigned int tamanho; unsigned char *ptr_p;
Apêndice B 141
tamanho = byte * altura; ptr_p = (unsigned char *) calloc(tamanho, sizeof(unsigned char)); if (!ptr_p) { fprintf(stderr, "Nao tem memoria suficiente para os pixels!\n"); exit(1); } return (ptr_p); } unsigned int TAMANHO (unsigned int largura) { unsigned int MOD, tamanho; /* --------- No. de pixels por linha ----------- */ MOD = largura % 8; if (MOD) tamanho = largura + (8 - MOD); else tamanho = largura; return (tamanho); } unsigned int TAM_IN_BYTE (unsigned int largura) { unsigned int byte, tamanho_largura; /* ------- No. de bytes por linha ------- */ tamanho_largura = TAMANHO (largura); byte = tamanho_largura / 8; return (byte); } void INITD (struct decode_estado *s, FILE *PCT) { int i; for (i = 0; i < 4096; s->ST[i++] = 0); s->CT = 0; s->C = 0; LERBYTE (s, PCT); s->C <<= 8; LERBYTE (s, PCT); s->C <<= 8; LERBYTE (s, PCT); s->A = 0x10000; return; } void plano (unsigned char *t, unsigned char *ptr, unsigned int lar, unsigned int alt) { unsigned char *q;
Apêndice B 142
unsigned int i, j, k; q = ptr; for (i = 0; i < alt; i++) { for (j = 0; j < lar; j++) { for (k = 0; k < 8; k++) { *q >>= 1; *q |= (*t & 0x80); q++; *t <<= 1; } t++; } } /* i */ return; } void DIVIDE (struct decode_estado *s, FILE *PCT, FILE *pix_final, char fn[]) { char letra; unsigned char *ptr, *bit; unsigned int i, cnt, x[20]; unsigned int largura, altura, nivel; unsigned int DL, D, NO_PLANO, espaco, liga, PT; unsigned int baixa_largura, baixa_altura, alta_byte, baixa_byte; fscanf(PCT,"%1d%1d%1d%1d%d%d%d%1d%d",&DL,&D,&NO_PLANO,&espaco,&largura,&altura,&nivel,&liga,&PT); if (D == 1) printf("\n\n A Decodificacao feita em cada PLANO somente para \ a camada com a resolucao total \n\n"); else printf ("\n\n A Decodificacao feita em cada PLANO somente para \ a menor camada de resolucao (D0) \n\n"); INITD (s, PCT); ptr = reserva_char (largura, altura); cnt = (D*2)-1; x[cnt--] = largura; x[cnt] = altura; for (i = 0; i < (D*2-2); i+=2) { x[--cnt] = (largura + 1)/2; largura = x[cnt--]; x[cnt] = (altura + 1)/2; altura = x[cnt]; } for (i = 0; i < NO_PLANO; i++) { if (D == 1)
Apêndice B 143
{ alta_byte = TAM_IN_BYTE (largura); bit = reserva_char (alta_byte, altura); DCOD5 (s, bit, largura, altura, alta_byte, alta_byte, liga, PT, PCT); plano (bit, ptr, alta_byte, altura); goto F; } /*** D ***/ cnt = 0; baixa_altura = x[cnt]; /* a medida da menor resolucao */ cnt += 1; baixa_largura = x[cnt]; baixa_byte = TAM_IN_BYTE (baixa_largura); bit = reserva_char (baixa_byte, baixa_altura); DCOD5 (s, bit, baixa_largura, baixa_altura, baixa_byte, baixa_byte, liga, PT, PCT); plano (bit, ptr, baixa_byte, baixa_altura); F: free (bit); } /* i */ fprintf (pix_final,"%d %d\n%d\n", largura, altura, nivel); MEM_W (ptr, altura, largura, pix_final, fn); free (ptr); return; } void CAMADAS (struct decode_estado *s, char *fe) { char fn[20]; FILE *PCT, *pix_final; unsigned char tipo, L; sprintf(fn,"Imagem-Rec.pgm"); pix_final = fopen(fn,"wb"); if (!pix_final) { fprintf (stderr,"Nao pode abrir o arquivo '%s' para escrever\n",fn); exit(1); } PCT = fopen(fe,"rb"); if (!PCT) { fprintf (stderr," Nao pode abrir o arquivo '%s' para ler\n",fe); exit(1); } if ((L = getc(PCT)) != 'P') { fprintf (stderr,"O arquivo '%s' nao e tipo PGM !\n",fe); exit(1); } if ((tipo = getc(PCT)) != '5') { fprintf (stderr,"O arquivo '%s' nao e com formato RAW de tipo PGM !\n",fe); exit(1); } fprintf (pix_final,"%c%c\n", L, tipo);
Apêndice B 144
while ((L = getc(PCT)) != EOF && !isdigit(L)) if (L =='#') { ungetc(L, PCT); while ((L = getc(PCT)) != EOF && !(L == 13 || L == 10)) fprintf (pix_final,"%c",L); fprintf (pix_final,"\n"); } ungetc(L, PCT); DIVIDE (s, PCT, pix_final, fn); if (ferror(PCT) || fclose(PCT)) { fprintf (stderr,"Problema durante lendo os pixels de '%s'\n",fe); exit(1); } return; } main(argc, argv) char *argv[]; { char *fe = argv[1]; struct decode_estado s; if (fe != NULL) { CAMADAS (&s, fe); printf ("\n\n ........ FIM DO PROCESSO DE DECODIFICACAO ........\n\n"); printf ("\n A imagem recuperada esta no arquivo chamado Re-imagem.pgm \n"); } else printf ("\n\n ---> 'erro'! Por favor, \n\n \ entre com nome do arquivo compactado.\n\n"); } /* main */
Apêndice B 145
2- Programas de codificação e decodificação (com modo progressivo) de imagem escala de cinzas com a nova proposta
/* --- Utilizando imagem (escala de cinzas) de formato ROW tipo PGM codificando --- */ /* ------- os planos de bits com suas resoluções totais sem dividi-los em camadas -------- */ /* ---------- de resolução, e com a opção de usar o processo de Predição Típica ---------- */ #include <assert.h> #include <stdlib.h> #include <ctype.h> #include <stdio.h> #include <math.h> #include "tabela.h" #define MARKER_STUFF 0X00 #define MARKER_SDNORM 0X02 #define MARKER_SDRST 0X03 #define MARKER_ESC 0XFF #define PTB2CX 0X195 #define PTB3CX 0X0E5 /* ------ Descricao "status" de codificador aritmetico ----- */ struct code_estado { unsigned char ST[4096]; /* "status" de prob. dos contextos, e MSB = MPS */ unsigned int C; /* registrador C, base de intervalo codificado */ int A; /* registrador A tamanho normalizado de intervalo */ int SC; /* contador de pilha */ int CT; /* contador dislocamento de bits, determina quando * proximo byte vai ser armazenado ou transmitido */ int BUF; /* buffer para armazenar recente byte da saida != 0xff */ char pt[]; /* buffer para valores temp. usados por Predição Tipical Dif. */ }; void BYTEOUT (int BUF, FILE *PCT) { putc (BUF, PCT); return; } void FIMC (struct code_estado *s, FILE *PCT) { int TEMP; /** procura no intervalo codificado s->c com maior numeros de bits zero **/ if ((TEMP = (s->A - 1 + s->C) & 0xffff0000) < s->C) s->C = TEMP + 0x8000;
Apêndice B 146
else s->C = TEMP; /* --------- envia o resto de bytes para o arquivo de sai'da --------- */ s->C <<= s->CT; if (s->C > 0x7ffffff) { /* um overflow final vai acontecer */ if (s->BUF >= 0) { BYTEOUT (s->BUF + 1, PCT); if (s->BUF + 1 == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); } if (s->C & 0x7fff800) for (; s->SC; --s->SC) BYTEOUT (0x00, PCT); } else { if (s->BUF >= 0) BYTEOUT (s->BUF, PCT); for (; s->SC; --s->SC) { BYTEOUT (0xff, PCT); BYTEOUT (MARKER_STUFF, PCT); } } /* -------- envia os bytes finais somente se nao sao 0x00 -------- */ if (s->C & 0x7fff800) { BYTEOUT ((s->C >> 19) & 0xff, PCT); if (((s->C >> 19) & 0xff) == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); if (s->C & 0x7f800) { BYTEOUT ((s->C >> 11) & 0xff, PCT); if (((s->C >> 11) & 0xff) == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); } } return; } void CODIF (struct code_estado *s, unsigned int CX, unsigned int PIX, FILE *PCT) { int TEMP; register int lsz, ss; extern short LSZ[]; extern char NLPS[], NMPS[], SWTCH[]; assert (CX >= 0 && CX < 4096); /* determine ST[CX] */
Apêndice B 147
ss = s->ST[CX] & 0x7f; /* para capturar somente primeiros 7 bits */ assert (ss >= 0 && ss < 113); /* determine LSZ[ST[CX]] */ lsz = LSZ[ss]; if (((PIX << 7) ^ s->ST[CX]) & 0x80) /* PIX != MPS[CX] */ { /* ------ codifica o simbolo de menor ocorrencia LPS ------- */ if ((s->A -= lsz) >= lsz) /* se intervalo de MPS >= LPS */ { s->C += s->A; s->A = lsz; } if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* MSB ===> MPS[CX]=1-MPS[CX] * * XOR se A = B, entao A XOR @ B = 0 */ s->ST[CX] &= 0x80; /* mantem somente o valor de MPS=MSB */ s->ST[CX] |= NLPS[ss]; } else { /* ------- Codificar o simbolo de maior ocorrencia MPS ------ */ if ((s->A -= lsz) >= 0x8000) return; /*--- se A >= 0x8000, nao precisa renormalizacao ---*/ if (s->A < lsz) { s->C += s->A; s->A = lsz; } s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } do /* -------- renormalizacao de intervalo codificado --------- */ { s->A <<= 1; s->C <<= 1; --s->CT; if (s->CT == 0) /* outro byte pronto p/ envia-lo p/ arquivo da saida */ { TEMP = s->C >> 19; /* TEMP = um byte (com o carry) de reg. C */ if (TEMP > 0xff) /* ----- contiudo de BUF ----- */ { /* -------- ocorre overflow -------- */ if (s->BUF >= 0) { ++s->BUF; BYTEOUT (s->BUF, PCT); if (s->BUF == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); } for (; s->SC; --s->SC) /* no final SC = 0 */ BYTEOUT (0x00, PCT); s->BUF = TEMP & 0xff; /*novo byte p/ enviar,talvez ocorrera overflow*/ assert (s->BUF != 0xff);
Apêndice B 148
} else if (TEMP == 0xff) /* talvez ocorrera overflow */ ++s->SC; else { /* nao ocorrera overflow */ if (s->BUF >= 0) BYTEOUT (s->BUF, PCT); for (; s->SC; --s->SC) /* no final SC = 0 */ { BYTEOUT (0xff, PCT); BYTEOUT (MARKER_STUFF, PCT); } s->BUF = TEMP; /* buffer p/ novo byte enviado */ } s->C &= 0x7ffff; s->CT = 8; } } while (s->A < 0x8000); return; } void COD5 (struct code_estado *s, unsigned char *Res_bit, unsigned int largura, unsigned int altura, unsigned int alta_byte, unsigned int liga, unsigned int PTBON, FILE *PCT) { unsigned char *lp1, *lp2, *p1, *q1; unsigned int cx, PIX, i, j, fase1, fase2; unsigned int lpt, lpt_antiga, CX_CBR, SLNPT; unsigned int linha_h1,linha_h2,linha_h3,linha_l1,linha_l2,linha_l3; /*** ------- codificar somente a camada total de cada Plano ------- ***/ /********** --- ou seja codificacao quando camada = 0 --- **********/ cx = 0; PIX = 0; lpt_antiga = 0; lp2 = Res_bit; lp1 = lp2 + alta_byte; for (i = 0; i < altura; i++) { /* ============ Predição Tipical Para Menor Camada ============ */ if (PTBON == 1) { p1 = lp2; if (i > 0) { q1 = lp2 - alta_byte; while (q1 < lp2 && (lpt = (*p1++ == *q1++)) != 0); } else /* a primeira linha */ while (p1 < lp2 + alta_byte && (lpt = (*p1++ == 0)) != 0); if (liga == 2) CX_CBR = 1; else
Apêndice B 149
CX_CBR = 0; SLNPT = !(lpt ^ lpt_antiga); CODIF (s, CX_CBR ? PTB2CX : PTB3CX, SLNPT, PCT); lpt_antiga = lpt; /** CX_CBR = PTB3CX caso CX_CBR = 0 **/ if (lpt) { /** Pular para próxima linha pois as duas linhas sao iquais **/ lp2 += alta_byte; /** area solida **/ continue; /** vai ate o final do loop for (i= ....) **/ } } /* if PTBON */ linha_h1 = linha_h2 = linha_h3 = 0; if (i > 0) { linha_h2 = (unsigned int) *(lp2 - alta_byte) << 8; if (i > 1 && liga == 3) linha_h3 = (unsigned int) *(lp2 - alta_byte - alta_byte) << 8; } /** codificacao da linha **/ for (j = 0; j < largura; lp2++) { linha_h1 |= *lp2; if ((j < (alta_byte * 8 - 8)) && (i > 0)) { linha_h2 |= *(lp2 - alta_byte + 1); if (i > 1 && liga == 3) linha_h3 |= *(lp2 - alta_byte - alta_byte + 1); } do { linha_h1 <<= 1; linha_h2 <<= 1; linha_h3 <<= 1; switch (liga) { case 2: /* template de duas linhas */ cx = (((linha_h1>> 9) & 0x00f) + ((linha_h2>> 10) & 0x3f0)); break; case 3: /* template de tres linhas */ cx = (((linha_h1>> 9) & 0x003) + ((linha_h2>> 12) & 0x07c) + ((linha_h3 >> 8) & 0x380)); break; default: fprintf (stderr,"Tipo de Template -%d- errado!\n" ,liga); exit(1); } PIX = ((linha_h1 >> 8) & 1); CODIF (s, cx, PIX, PCT); cx = 0; } while (++j & 7 && j < largura); } /* j */ } /* i */ return; } unsigned int TAMANHO (unsigned int largura) {
Apêndice B 150
unsigned int tamanho, MOD; /* --------- No. de pixels por linha ----------- */ MOD = largura % 8; if (MOD) tamanho = largura + (8 - MOD); else tamanho = largura; return (tamanho); } unsigned int TAM_IN_BYTE (unsigned int largura) { unsigned int byte, tamanho_largura; /* ------- No. de bytes por linha ------- */ tamanho_largura = TAMANHO (largura); byte = tamanho_largura / 8; return (byte); } void DIVIDE (struct code_estado *s, unsigned int nova_lar, unsigned int altura, unsigned int liga, unsigned int PT, FILE *PCT, unsigned char *b) { unsigned int alta_byte; /*** ------- codificar somente a camada total de cada Plano ------- ***/ /************ ------------------------------------------- ************/ alta_byte = TAM_IN_BYTE (nova_lar); COD5(s, b, nova_lar, altura, alta_byte, liga, PT, PCT); BYTEOUT (MARKER_ESC, PCT); BYTEOUT (MARKER_SDNORM, PCT); return; } void **PLANO_P (unsigned int largura, unsigned int altura, unsigned char *bit, unsigned char **g) { unsigned char *k; unsigned int i, j; unsigned char *b0, *b1, *b2, *b3, *b4, *b5, *b6, *b7; /* -------- Colocar os dados de cada bit de 8 bits -------- */ /* ------------- numa area de memoria separada ------------ */ b0 = g[0]; b1 = g[1]; b2 = g[2]; b3 = g[3]; b4 = g[4]; b5 = g[5]; b6 = g[6]; b7 = g[7]; k = bit; for (i = 0; i < altura; i++) { for (j = 0; j < largura; j++) { *b0 <<= 1; *b0 |= (*k & 0x01); *k >>= 1; *b1 <<= 1; *b1 |= (*k & 0x01); *k >>= 1; *b2 <<= 1; *b2 |= (*k & 0x01); *k >>= 1;
Apêndice B 151
*b3 <<= 1; *b3 |= (*k & 0x01); *k >>= 1; *b4 <<= 1; *b4 |= (*k & 0x01); *k >>= 1; *b5 <<= 1; *b5 |= (*k & 0x01); *k >>= 1; *b6 <<= 1; *b6 |= (*k & 0x01); *k >>= 1; *b7 <<= 1; *b7 |= (*k & 0x01); if ((j & 7) == 7) { b0++; b1++; b2++; b3++; b4++; b5++; b6++; b7++; } k++; } } /* i */ return; } void MEM_R (unsigned char *ptr, unsigned int altura, unsigned int alta_byte, FILE *fpix, char *fe) { fread (ptr, alta_byte * altura, sizeof(unsigned char), fpix); if (feof(fpix)) { fprintf (stderr, "Fim do arquivo de pixels '%s' inesperado !\n",fe); exit(1); } if (ferror(fpix) || fclose(fpix)) { fprintf (stderr,"Problema durante a leitura do arquivo '%s'\n",fe); exit(1); } return; } unsigned int lerint (FILE *fpix) { unsigned int i, c; if ((c = getc(fpix)) != EOF) { ungetc(c, fpix); fscanf(fpix,"%d",&i); } return i; } unsigned char *reserva_char (unsigned int byte, unsigned int altura) /* -------- Reservando uma area com valores zeros nela -------- */ { unsigned int tamanho; unsigned char *ptr_p; tamanho = byte * altura; ptr_p = (unsigned char *) calloc(tamanho, sizeof(unsigned char)); if (!ptr_p)
Apêndice B 152
{ fprintf (stderr, "Nao tem memoria suficiente para os pixels!\n"); exit(1); } return (ptr_p); } FILE *ABRIR (char *f, FILE *PCT) { FILE *fpix; unsigned int k; unsigned char L, tipo; fpix = fopen(f,"rb"); if (!fpix) { fprintf (stderr,"Nao pode abrir o arquivo de pixels '%s'\n",f); exit(1); } if ((L = getc(fpix)) != 'P') { fprintf (stderr,"O arquivo '%s' nao e tipo PGM !\n",f); exit(1); } fwrite (&L, 1, sizeof(unsigned char), PCT); if ((tipo = getc(fpix)) != '5') { fprintf (stderr,"O arquivo '%s' nao e com formato RAW de tipo PGM !\n",f); exit(1); } fwrite (&tipo, 1, sizeof(unsigned char), PCT); fprintf (PCT,"\n"); while ((k = getc(fpix)) != EOF && !isdigit(k)) if (k =='#') { ungetc(k, fpix); while ((k = getc(fpix)) != EOF && !(k == 13 || k == 10)) fprintf (PCT,"%c",k); fprintf (PCT,"\n"); } ungetc(k, fpix); return (fpix); } void CAMADAS (struct code_estado *s, char *fs, char *fe) { FILE *fpix, *PCT; unsigned char *area, **PLANO, h; unsigned int espaco, DL, D, NO_PLANO, liga, PT, m; unsigned int largura, altura, nivel, nova_lar, lar; unsigned char *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7; PCT = fopen(fs,"wb");
Apêndice B 153
if (!PCT) { fprintf (stderr,"Nao pode abrir o arquivo '%s' de saida \n",fs); exit(1); } fpix = ABRIR (fe, PCT); printf ("\n\n ========>> ATENCAO! ... O numero de PLANOS = 8 \n\n"); NO_PLANO = 8; DL = 0; printf ("\n\n ==> Digite 1 para ativar processo da Predição Tipical = "); scanf ("%d",&PT); if (PT == 1) printf ("\n ---- Codificaco Progressiva Com a Opcao PT ----\n"); else printf ("\n ---- Codificaco Progressiva sem Usar a Opcao PT ----\n"); C: printf ("\n\n =======>> Entre com numeros de Camadas de Resolucao = "); scanf ("%d",&D); if (D > 7 || D == 0) { printf ("\n O padrao JBIG ADEVERTE! o valor de camadas deveria ser \ entre (1) e (7). ===> Por favor, repeta-se o processo ... \n\n"); goto C; } printf("\n\n ATENCAO! ... A codificacao feita em cada PLANO para \ somente a camada de resolucao total .... \n\n"); espaco = 0; largura = lerint (fpix); altura = lerint (fpix); h = getc(fpix); nivel = lerint (fpix); h = getc(fpix); /* ----- Colocar os dados da imagem original numa area ----- */ area = reserva_char (largura, altura); MEM_R (area, altura, largura, fpix, fe); /* ------- Reservar uma area para cada bit de 8 bits ------- */ /* ------------------ da imagem original ------------------- */ PLANO = (unsigned char **) calloc(NO_PLANO, sizeof(unsigned char)); if (!PLANO) { fprintf (stderr, "Nao tem memoria suficiente para a reserva!\n"); exit(1); } lar = largura / 8; /*- Medida nova para nova area de cada bit (PLANO) -*/ for (m = 0; m < NO_PLANO; m++) PLANO[m] = reserva_char (lar, altura); /* - Colocar os dados de cada bit de cada byte separados na memoria - */ t0 = PLANO[0]; t1 = PLANO[1]; t2 = PLANO[2]; t3 = PLANO[3]; t4 = PLANO[4]; t5 = PLANO[5]; t6 = PLANO[6]; t7 = PLANO[7]; PLANO_P (largura, altura, area, PLANO); free (area); fprintf (PCT,"%d", DL); fprintf (PCT,"%d", D); fprintf (PCT,"%d", NO_PLANO); fprintf (PCT,"%d", espaco); fprintf (PCT," %d %d ", largura, altura); fprintf (PCT,"%d ", nivel); printf ("\n Modelo Template de Baixa Res. : - Duas linhas => digite 2:");
Apêndice B 154
printf ("\n - Tres linhas => digite 3:"); scanf ("%d",&liga); fprintf(PCT,"%d",liga); fprintf (PCT,"%d", PT); nova_lar = lar * 8; /* -- # de bits por linha em cada PLANO = largura -- */ DIVIDE (s, nova_lar, altura, liga, PT, PCT, t0); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t1); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t2); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t3); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t4); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t5); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t6); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t7); FIMC (s, PCT); free(PLANO); if (ferror(PCT) || fclose(PCT))
INITC (&s);
{ fprintf (stderr,"Problema durante escrever no arquivo '%s'\n",fs); exit(1); } return; } void INITC (struct code_estado *s) { int i; for (i = 0; i < 4096; s->ST[i++] = 0); s->C = 0; s->A = 0x10000; s->SC = 0; s->CT = 11; s->BUF = -1; /* buffer vazio */ return; }
main (argc, argv) char *argv[]; { struct code_estado s; char *fe = argv[1], *fs = argv[2]; printf ("\n\n ===> Os arquivos de entrada e saida: %s e %s\n",fe, fs); if ((fe != NULL) && (fs != NULL)) {
CAMADAS (&s, fs, fe); printf ("\n\n------>> O tamanho total = %d bytes \n", tamanho_total); printf (" \n\n...... FIM DO PROCESSO DE CODIFICACAO ......\n\n"); } else printf ("'erro'! \n\n Por favor, entre com: nome do arquivo tipo PGM \ e da saida para armazenar os dados compactados, sequencialmente.\n"); } /* main */
Apêndice B 155
/* --- Utilizando imagem (escala de cinzas) de formato ROW tipo PGM decodificando --- */ /* ---- a alta camada de resolução de cada plano e construir as camadas diferenciais ----- */ /* --------------------- com a opção de usar o processo de Predição Típica --------------------- */ #include <stdio.h> #include <ctype.h> #include <assert.h> #include <stdlib.h> #include "tabela.h" #define MARKER_STUFF 0X00 #define MARKER_SDNORM 0X02 #define MARKER_SDRST 0X03 #define MARKER_ESC 0XFF #define PTB2CX 0X195 #define PTB3CX 0X0E5 /* ------ Descricao "status" de decodificador aritmetico ----- */ struct decode_estado { unsigned char ST[4096]; /* "status" prob. dos contextos, e MSB = MPS */ unsigned int C; /* registrador C, base de intervalo a ser codificado*/ int A; /* registrador A, tamanho normalizado de intervalo */ int CT; /* contador de dislocamento de bits, determina * * quando pro'ximo byte vai ser lido */ int lnpt; /* flag de PT: linha nao e' Predicao Tipical */ }; void LERBYTE (struct decode_estado *s, FILE *PCT) { unsigned int k; L: if ((k = getc(PCT)) != EOF) { if (k == MARKER_ESC) { if ((k = getc(PCT)) == EOF) { printf ("\n Erro! No codigo do Encerramento, surgeu 0xff extra!\n"); exit(1); } else if (k == MARKER_SDNORM) goto L; else if (k == MARKER_SDRST) { printf ("\n\n O fim dos dados da camada, encerramento reforcado \n"); goto L;
Apêndice B 156
} else if (k == MARKER_STUFF) k = 0xff; else { printf ("\n Erro! Nao ha codigo de STUFF \n\n"); exit(1); } } } else k = 0; s->C |= k << 8; s->CT = 8; return; } void RENORMDEC (struct decode_estado *s, FILE *PCT) {
LERBYTE (s, PCT);
do { if (s->CT == 0) LERBYTE (s, PCT); s->C <<= 1; s->A <<= 1; --s->CT; } while (s->A < 0x8000); if (s->CT == 0)
return; } unsigned int DECODIF (struct decode_estado *s, FILE *PCT, unsigned short CX) { unsigned int PIX; extern short LSZ[]; register int lsz, ss; extern char NMPS[], NLPS[], SWTCH[];
ss = s->ST[CX] & 0x7f; /* determina o estado do contexto CX */ assert (ss < 113); lsz = LSZ[ss]; /* consulta a estimativa de probabilidade relativa ao estado do CX */ if ((s->C >> 16) < (s->A -= lsz)) if (s->A >= 0x8000) { PIX = s->ST[CX] >> 7; return PIX; } else /* ----------- MPSDECODIF ----------- */ if (s->A < lsz) { PIX = 1 - (s->ST[CX] >> 7);
Apêndice B 157
/* --- teste se a troca condicional (MPS/LPS) e' necessa ria --- */ if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* XOR para invertir o valor de MVAL[CX] */ /* - escolha o proximo estado de estimativa de probabilidade - */ s->ST[CX] &= 0x80; s->ST[CX] |= NLPS[ss]; } else { PIX = s->ST[CX] >> 7; s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } else /* ----------- LPSDECODIF ----------- */ if (s->A < lsz)
s->C -= s->A << 16;
s->ST[CX] |= NLPS[ss];
unsigned int cx, PIX, fase1, fase2;
{ s->C -= s->A << 16; s->A = lsz; PIX = s->ST[CX] >> 7; s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } else {
s->A = lsz; PIX = 1 - (s->ST[CX] >> 7); /* --- teste se a troca condicional (MPS/LPS) e necessaria --- */ if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* XOR para invertir o valor de MVAL[CX] */ /* - escolha o proximo estado de estimativa de probabilidade - */ s->ST[CX] &= 0x80;
} RENORMDEC (s, PCT); return PIX; } void DCOD5 (struct decode_estado *s, unsigned char *Res_bit, unsigned int largura, unsigned int altura, unsigned int alta_byte, unsigned int liga, unsigned int PTBON, FILE *PCT) { unsigned int i, j, CX_CBR, SLNPT; unsigned char *lp1, *lp2, *p1, *q1;
register unsigned int linha_h1,linha_h2,linha_h3,linha_l1,linha_l2,linha_l3; /*** ------- codificar somente a camada total de cada Plano ------- ***/ /********** --- ou seja codificacao quando camada = 0 --- **********/ cx = 0;
Apêndice B 158
PIX = 0; s->lnpt = 1; lp2 = Res_bit; lp1 = lp2 + alta_byte; for (i = 0; i < altura; i++)
s->lnpt = !(SLNPT ^ s->lnpt); /** se A=B entao A.XOR.B=0 **/
{ /* =============== Predição Tipical =============== */ if (PTBON == 1) { if (liga == 2) CX_CBR = 1; else CX_CBR = 0; SLNPT = DECODIF (s, PCT, CX_CBR ? PTB2CX : PTB3CX);
if (!s->lnpt) { /* linha tipical (iqual a linha em cima dela) */ p1 = lp2; if (i == 0) while (p1 < lp2 + alta_byte) *p1++ = 0; else { q1 = lp2 - alta_byte; while (q1 < lp2) *p1++ = *q1++; } /* else */ lp2 += alta_byte; continue; } /* if */ } /* if PTBON */ linha_h1 = linha_h2 = linha_h3 = 0; if (i > 0) { linha_h2 = (unsigned int) *(lp2 - alta_byte) << 8; if (i > 1 && liga == 3) linha_h3 = (unsigned int) *(lp2 - alta_byte - alta_byte) << 8; } /**** decodificacao da linha ****/ for (j = 0; j < largura;) { if ((j & 7) == 0) if ((j < (alta_byte * 8 - 8)) && (i > 0)) { linha_h2 |= *(lp2 - alta_byte + 1); if (i > 1 && liga == 3) linha_h3 |= *(lp2 - alta_byte - alta_byte + 1); } do { switch (liga) { case 2: /* template de duas linhas */
Apêndice B 159
cx = (linha_h1 & 0x00f) + ((linha_h2 >> 9) & 0x3f0); break; case 3: /* template de tres linhas */ cx = (linha_h1 & 0x003) + ((linha_h2 >> 11) & 0x07c) + ((linha_h3 >> 7) & 0x380); linha_h3 <<= 1; break; default: fprintf (stderr,"Tipo de Template -%d- errado!\n" ,liga); exit(1); }
} /* i */
PIX = DECODIF (s, PCT, cx); cx = 0; linha_h1 <<= 1; linha_h1 |= (PIX & 1); linha_h2 <<= 1; } while (++j & 7 && j < largura); *lp2 = linha_h1; lp2++; } /* j */ *(lp2 - 1) <<= alta_byte * 8 - largura;
return; } void MEM_W (unsigned char *bit, unsigned int altura, unsigned int alta_byte, FILE *pix_final, char fn[]) { fwrite (bit, alta_byte * altura, sizeof(unsigned char), pix_final); if (ferror(pix_final) || fclose(pix_final)) { fprintf (stderr,"Problema no escrito dos pixels em '%s'\n",fn); exit(1); } return; } unsigned char *reserva_char (unsigned int byte, unsigned int altura) /* -------- Reservando uma area com valores zeros nela -------- */ { unsigned int tamanho; unsigned char *ptr_p;
tamanho = byte * altura; ptr_p = (unsigned char *) calloc(tamanho, sizeof(unsigned char)); if (!ptr_p) { fprintf(stderr, "Nao tem memoria suficiente para os pixels!\n"); exit(1); } return (ptr_p); }
Apêndice B 160
unsigned int TAMANHO (unsigned int largura) { unsigned int MOD, tamanho; /* --------- No. de pixels por linha ----------- */ MOD = largura % 8; if (MOD) tamanho = largura + (8 - MOD); else tamanho = largura; return (tamanho); }
s->A = 0x10000;
unsigned int TAM_IN_BYTE (unsigned int largura) { unsigned int byte, tamanho_largura; /* ------- No. de bytes por linha ------- */ tamanho_largura = TAMANHO (largura); byte = tamanho_largura / 8; return (byte); }
void INITD (struct decode_estado *s, FILE *PCT) { int i; for (i = 0; i < 4096; s->ST[i++] = 0); s->CT = 0; s->C = 0; LERBYTE (s, PCT); s->C <<= 8; LERBYTE (s, PCT); s->C <<= 8; LERBYTE (s, PCT);
return; } void plano (unsigned char *t, unsigned char *ptr, unsigned char *orig, unsigned int bytes, unsigned int alt) { unsigned int i, j, k; unsigned char *q, *p; /** colocar os dados da area t na area ptr (cada byte de t colocado em 8 bytes de ptr) **/ /** e tambem coloca-los na area orig de mesmo jeito de ptr, e cada byte e' deslocado **/ /************* um bit para reseber proximos dados de outros planos *************/ q = ptr; p = orig; for (i = 0; i < alt; i++) { for (j = 0; j < bytes; j++) { for (k = 0; k < 8; k++) {
Apêndice B 161
*q >>= 1; *q |= (*t & 0x80); q++; *p >>= 1; *p |= (*t & 0x80); p++; *t <<= 1; } t++; } } /* i */ return; } unsigned int x[20]; void SAIDA (unsigned char **bit, unsigned char *orig, unsigned int i, unsigned int nivel, unsigned int D, char fn[]) { FILE *pix_final; unsigned char *ptr; unsigned int cnt, ca, alta_byte; cnt = 0; ptr = reserva_char (x[cnt], x[cnt+1]); /*** onde x[cnt] = largura ***/ alta_byte = TAM_IN_BYTE (x[cnt]); /*** e x[cnt+1] = altura ***/ /*** criar a alta camada de cada plano e salva-la num arquivo ***/ plano (bit[0], ptr, orig, alta_byte, x[cnt+1]); sprintf(fn,"PLANO[%d]-D%d.pgm", i, D-1); pix_final = fopen(fn,"wb"); if (!pix_final) { fprintf (stderr,"Nao pode abrir o arquivo '%s' para escrever\n",fn); exit(1); } fprintf (pix_final,"%c%c\n", 'P', '5'); fprintf (pix_final,"%d %d\n%d\n", x[cnt], x[cnt+1], nivel); MEM_W (ptr, x[cnt+1], x[cnt], pix_final, fn); free (ptr); return; } void REDUZIR (unsigned char **bit, unsigned char *pln, unsigned int D, unsigned int nova_lar, unsigned int altura) { extern char Map[]; unsigned char *Meio, *F, *Pr, *P_baixa; unsigned int cnt, chave, ca, i, j, Resultado, cont_a, cont_b; unsigned short linha_F, linha_Meio, linha_Pr, linha_baixa2, baixa_pix; unsigned int baixa_nova_lar, baixa_altura, alta_byte, baixa_byte, baixa_L_tamanho;
Apêndice B 162
cnt = 0; chave = 1; for (ca = 1; ca < D; ca++) { if (chave != 0) { x[cnt] = nova_lar; cnt += 1; x[cnt] = altura; alta_byte = TAM_IN_BYTE (nova_lar); bit[ca-1] = pln; chave = 0; } Meio = bit[ca-1]; F = Meio - alta_byte; Pr = Meio + alta_byte; baixa_nova_lar = (nova_lar + 1)/2; baixa_altura = (altura + 1)/2; cnt += 1; x[cnt] = baixa_nova_lar; cnt += 1; x[cnt] = baixa_altura; baixa_L_tamanho = TAMANHO (baixa_nova_lar); baixa_byte = baixa_L_tamanho / 8; bit[ca] = reserva_char (baixa_byte, baixa_altura); P_baixa = bit[ca]; for (i = 0; i < baixa_altura; i++) { if (2 * i + 1 >= altura) Pr = Meio; /* -- para repetir ultima linha da imagem no final -- */ baixa_pix = 0; linha_F = linha_Meio = linha_Pr = linha_baixa2 = 0; for (j = 0; j < baixa_L_tamanho; j += 8) { *P_baixa = 0; linha_baixa2 |= i ? *(P_baixa - baixa_byte) : 0; /* --- linha_baixa2 = 0 caso i=0, e caso contrario pega --- */ /* --- o byte que esta a cima do byte atual do P_baixa --- */ for (cont_b=0; cont_b < 8 && j+cont_b < baixa_nova_lar; cont_b += 4) { if (((j + cont_b) >> 2) < alta_byte) { /* --- p/ evitar passar o limite de bytes na alta Res. --- */ linha_F |= i ? *F : 0; ++F; linha_Meio |= *Meio; ++Meio; linha_Pr |= *Pr; ++Pr; } for(cont_a=0;cont_a<4 && j+cont_b+cont_a<baixa_nova_lar; cont_a++) { linha_Pr <<= 2;
Apêndice B 163
linha_Meio <<= 2; linha_F <<= 2; linha_baixa2 <<= 1; Resultado = 0; Resultado = (((linha_Pr>>8) & 0x0007)+((linha_Meio>>5)& 0x0038) + ((linha_F >> 2) & 0x01c0) + (baixa_pix << 9) + ((linha_baixa2 << 2) & 0x0c00)); assert (Resultado >= 0 && Resultado < 4096); baixa_pix = 0; baixa_pix = Map[Resultado]; *P_baixa <<= 1; *P_baixa |= (unsigned char) baixa_pix; /** P_baixa e linha atual na baixa Res. **/ } /* --- baixa_pix e linha a cima do pixel ? estimado --- */ } ++P_baixa; } /* j */ /* ----- inserir bits de valores zeros no final de cada linha ----- */ /* ----- ate atengir ao tamanho de baixa_L_tamanho ----- */ *(P_baixa - 1) <<= baixa_L_tamanho - baixa_nova_lar;/** recua P_baixa */ F += alta_byte; /* para um byte ai colocand 0's nas digitos de byte */ Meio += alta_byte; Pr += alta_byte; /* pula 1 line p/ repetir o processo na 3 e 4 linha */ } /* i */ nova_lar = baixa_nova_lar; altura = baixa_altura; alta_byte = baixa_byte; } /* ca */ return; } void DIVIDE (struct decode_estado *s, FILE *PCT, char fn[]) { FILE *pix_final; unsigned char L, *pln, *orig, **bit; unsigned int largura, altura, alta_byte; unsigned int i, DL, D, NO_PLANO, espaco, PT, nivel, liga; while ((L = getc(PCT)) != EOF && !isdigit(L)) if (L =='#') { ungetc(L, PCT); while ((L = getc(PCT)) != EOF && !(L == 13 || L == 10)); } ungetc(L, PCT); fscanf (PCT,"%1d%1d%1d%1d%d%d%d%1d%d",&DL,&D,&NO_PLANO,&espaco,&largura,&altura,&nivel,&liga,&PT); if (D == 1) printf("\n A Decodificacao feita em cada PLANO somente para a camada com a resolucao total \n\n"); else printf ("\n\n A Decodificacao feita em cada PLANO para D camadas de resolucao \n\n");
Apêndice B 164
INITD (s, PCT); bit = (unsigned char **) calloc(D, sizeof(unsigned char)); if (!bit) { fprintf (stderr, "Nao tem memoria suficiente para a reserva!\n"); exit(1); } orig = reserva_char (largura, altura); alta_byte = TAM_IN_BYTE (largura); for (i = 0; i < NO_PLANO; i++) { pln = reserva_char (alta_byte, altura); DCOD5 (s, pln, largura, altura, alta_byte, liga, PT, PCT); REDUZIR (bit, pln, D, largura, altura); /* criar camadas diferenciais */ SAIDA (bit, orig, i, nivel, D, fn); /* salvar as camadas em arquivos */ free (pln); } /* i (PLANO) */ sprintf(fn,"imagem_original.pgm"); pix_final = fopen(fn,"wb"); if (!pix_final) { fprintf (stderr,"Nao pode abrir o arquivo '%s' para escrever\n",fn); exit(1); } fprintf (pix_final,"%c%c\n", 'P', '5'); fprintf (pix_final,"%d %d\n%d\n", largura, altura, nivel); MEM_W (orig, altura, largura, pix_final, fn); free (orig); free (bit); return; } void CAMADAS (struct decode_estado *s, char *fe) { FILE *PCT; char fn[20]; unsigned char tipo, L; PCT = fopen(fe,"rb"); if (!PCT) { fprintf (stderr," Nao pode abrir o arquivo '%s' para ler\n",fe); exit(1); } if ((L = getc(PCT)) != 'P') { fprintf (stderr,"O arquivo '%s' nao e tipo PGM !\n",fe); exit(1); } if ((tipo = getc(PCT)) != '5') { fprintf (stderr,"O arquivo '%s' nao e com formato RAW de tipo PGM !\n",fe); exit(1);
Apêndice B 165
} DIVIDE (s, PCT, fn); if (ferror(PCT) || fclose(PCT)) { fprintf (stderr,"Problema durante lendo os pixels de '%s'\n",fe); exit(1);
} return; } main(argc, argv) char *argv[]; { char *fe = argv[1]; struct decode_estado s; if (fe != NULL) { CAMADAS (&s, fe); printf ("\n\n ...... FIM DO PROCESSO DE DECODIFICACAO ...... \n\n"); } else printf ("\n\n ---> 'erro'! Por favor, \n\n \ entre com nome do arquivo compactado.\n\n"); } /* main */
Apêndice B 166
3- Programas de codificação e decodificação (com modo progressivo) de imagem colorida com a nova proposta
int SC; /* contador de pilha */
/* ------- Utilizando imagem (colorida) de formato ROW tipo PGM codificando ------- */ /* ------- os planos de bits com suas resoluções totais sem dividi-los em camadas ------- */ /* ---------- de resolução, e com a opção de usar o processo de Predição Típica --------- */ nclude <math.h> #include <ctype.h> #include <stdio.h> #include <assert.h> #include <stdlib.h> #include "tabela.h" #define MARKER_STUFF 0X00 #define MARKER_SDNORM 0X02 #define MARKER_SDRST 0X03 #define MARKER_ESC 0XFF #define PTB2CX 0X195 #define PTB3CX 0X0E5 /* ------ Descricao "status" de codificador aritmetico ----- */ struct code_estado { unsigned char ST[4096]; /* "status" de prob. dos contextos, e MSB = MPS */ unsigned int C; /* registrador C, base de intervalo codificado */ int A; /* registrador A tamanho normalizado de intervalo */
int CT; /* contador dislocamento de bits, determina quando * proximo byte vai ser armazenado ou transmitido */ int BUF; /* buffer para armazenar recente byte da saida != 0xff */ char pt[]; /* buffer para valores temp. usados por Predição Tipical Dif. */ }; void BYTEOUT (int BUF, FILE *PCT) { putc (BUF, PCT); return; } void FIMC (struct code_estado *s, FILE *PCT) { int TEMP; /** procura no intervalo codificado s->c com maior numeros de bits zero **/ if ((TEMP = (s->A - 1 + s->C) & 0xffff0000) < s->C) s->C = TEMP + 0x8000; else s->C = TEMP;
Apêndice B 167
/* --------- envia o resto de bytes para o arquivo de saida --------- */ s->C <<= s->CT; if (s->C > 0x7ffffff) { /* um overflow final vai acontecer */ if (s->BUF >= 0) { BYTEOUT (s->BUF + 1, PCT); if (s->BUF + 1 == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); } if (s->C & 0x7fff800) for (; s->SC; --s->SC) BYTEOUT (0x00, PCT); } else { if (s->BUF >= 0) BYTEOUT (s->BUF, PCT); for (; s->SC; --s->SC) { BYTEOUT (0xff, PCT); BYTEOUT (MARKER_STUFF, PCT); } } /* -------- envia os bytes finais somente se nao sao 0x00 -------- */ if (s->C & 0x7fff800) { BYTEOUT ((s->C >> 19) & 0xff, PCT); if (((s->C >> 19) & 0xff) == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); if (s->C & 0x7f800) { BYTEOUT ((s->C >> 11) & 0xff, PCT);
extern short LSZ[];
if (((s->C >> 11) & 0xff) == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); } } return; } void CODIF (struct code_estado *s, unsigned int CX, unsigned int PIX, FILE *PCT) { int TEMP;
register int lsz, ss; extern char NLPS[], NMPS[], SWTCH[]; assert (CX >= 0 && CX < 4096); /* determine ST[CX] */ ss = s->ST[CX] & 0x7f; /* para capturar somente primeiros 7 bits */ assert (ss >= 0 && ss < 113); /* determine LSZ[ST[CX]] */ lsz = LSZ[ss];
Apêndice B 168
if (((PIX << 7) ^ s->ST[CX]) & 0x80) /* PIX != MPS[CX] */ { /* ------ codifica o simbolo de menor ocorrencia LPS ------- */
else
if ((s->A -= lsz) >= lsz) /* se intervalo de MPS >= LPS */ { s->C += s->A; s->A = lsz; } if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* MSB ===> MPS[CX]=1-MPS[CX] */ s->ST[CX] &= 0x80; /* mantem somente o valor de MPS=MSB */ s->ST[CX] |= NLPS[ss]; }
{ /* ------- Codificar o simbolo de maior ocorrencia MPS ------ */ if ((s->A -= lsz) >= 0x8000) return; /*--- se A >= 0x8000, nao precisa renormalizacao ---*/ if (s->A < lsz) { s->C += s->A; s->A = lsz; } s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } do /* -------- renormalizacao de intervalo codificado --------- */ { s->A <<= 1; s->C <<= 1; --s->CT; if (s->CT == 0) /* outro byte pronto p/ envia-lo p/ arquivo da saida */ { TEMP = s->C >> 19; /* TEMP = um byte (com o carry) de reg. C */ if (TEMP > 0xff) /* ----- contiudo de BUF ----- */ { /* -------- ocorre overflow -------- */ if (s->BUF >= 0) { ++s->BUF; BYTEOUT (s->BUF, PCT); if (s->BUF == MARKER_ESC) BYTEOUT (MARKER_STUFF, PCT); } for (; s->SC; --s->SC) /* no final SC = 0 */ BYTEOUT (0x00, PCT); s->BUF = TEMP & 0xff; /*novo byte p/ enviar,talvez ocorrera overflow*/ assert (s->BUF != 0xff); } else if (TEMP == 0xff) /* talvez ocorrera overflow */ ++s->SC; else { /* nao ocorrera overflow */
Apêndice B 169
if (s->BUF >= 0) BYTEOUT (s->BUF, PCT); for (; s->SC; --s->SC) /* no final SC = 0 */ { BYTEOUT (0xff, PCT); BYTEOUT (MARKER_STUFF, PCT); } s->BUF = TEMP; /* buffer p/ novo byte enviado */ } s->C &= 0x7ffff; s->CT = 8; } } while (s->A < 0x8000); return; } void COD6 (struct code_estado *s, unsigned char *Res_bit, unsigned int largura, unsigned int altura, unsigned int alta_byte, unsigned int liga, unsigned int PTBON, FILE *PCT) { unsigned char *lp1, *lp2, *p1, *q1; unsigned int cx, PIX, i, j, fase1, fase2; unsigned int lpt, lpt_antiga, CX_CBR, SLNPT; unsigned int linha_h1, linha_h2, linha_h3, linha_l1, linha_l2, linha_l3; /*** codificar somente a alta total de cada Plano ou seja codificacao quando camada = 0 ***/ cx = 0; PIX = 0; lpt_antiga = 0; lp2 = Res_bit; lp1 = lp2 + alta_byte; for (i = 0; i < altura; i++) { /* ============ Predição Tipical Para Menor Camada ============ */ if (PTBON == 1) { p1 = lp2; if (i > 0) { q1 = lp2 - alta_byte; while (q1 < lp2 && (lpt = (*p1++ == *q1++)) != 0); } else /* a primeira linha */ while (p1 < lp2 + alta_byte && (lpt = (*p1++ == 0)) != 0); if (liga == 2) CX_CBR = 1; else CX_CBR = 0; SLNPT = !(lpt ^ lpt_antiga); CODIF (s, CX_CBR ? PTB2CX : PTB3CX, SLNPT, PCT); lpt_antiga = lpt; /** CX_CBR = PTB3CX caso CX_CBR = 0 **/ if (lpt) { /** Pular para próxima linha pois as duas linhas sao iquais **/ lp2 += alta_byte; /** area solida **/
Apêndice B 170
continue; /** vai ate o final do loop for (i= ....) **/ } } /* if PTBON */ linha_h1 = linha_h2 = linha_h3 = 0; if (i > 0) { linha_h2 = (unsigned int) *(lp2 - alta_byte) << 8; if (i > 1 && liga == 3)
}
{ linha_h1 <<= 1; linha_h2 <<= 1; linha_h3 <<= 1; switch (liga)
cx = (((linha_h1>> 9) & 0x003) + ((linha_h2>> 12) & 0x07c) + ((linha_h3 >> 8) & 0x380)); break; default: fprintf (stderr,"Tipo de Template -%d- errado!\n" ,liga); exit(1);
cx = 0;
MOD = largura % 8;
linha_h3 = (unsigned int) *(lp2 - alta_byte - alta_byte) << 8; } /** codificacao da linha **/ for (j = 0; j < largura; lp2++) { linha_h1 |= *lp2; if ((j < (alta_byte * 8 - 8)) && (i > 0)) { linha_h2 |= *(lp2 - alta_byte + 1); if (i > 1 && liga == 3) linha_h3 |= *(lp2 - alta_byte - alta_byte + 1);
do
{ case 2: /* template de duas linhas */ cx = (((linha_h1>> 9) & 0x00f) + ((linha_h2>> 10) & 0x3f0)); break; case 3: /* template de tres linhas */
} PIX = ((linha_h1 >> 8) & 1); CODIF (s, cx, PIX, PCT);
} while (++j & 7 && j < largura); } /* j */ } /* i */ return; } unsigned int TAMANHO (unsigned int largura) { unsigned int tamanho, MOD;
/* --------- No. de pixels por linha ----------- */
if (MOD) tamanho = largura + (8 - MOD); else
Apêndice B 171
tamanho = largura; return (tamanho); }
{
BYTEOUT (MARKER_SDNORM, PCT);
unsigned char *k;
b0 = g[0]; b1 = g[1]; b2 = g[2]; b3 = g[3];
k = bit;
unsigned int TAM_IN_BYTE (unsigned int largura)
unsigned int byte, tamanho_largura; /* ------- No. de bytes por linha ------- */ tamanho_largura = TAMANHO (largura); byte = tamanho_largura / 8; return (byte); } void DIVIDE (struct code_estado *s, unsigned int nova_lar, unsigned int altura, unsigned int liga, unsigned int PT, FILE *PCT, unsigned char *b) { unsigned int alta_byte; /*** ------ codificar somente a alta total de cada Plano ------ ***/ alta_byte = TAM_IN_BYTE (nova_lar); COD6(s, b, nova_lar, altura, alta_byte, liga, PT, PCT); BYTEOUT (MARKER_ESC, PCT);
return; } void **PLANO_P (unsigned int largura, unsigned int altura, unsigned char *bit, unsigned char **g) {
unsigned int i, j; unsigned char *b0, *b1, *b2, *b3, *b4, *b5, *b6, *b7; /* -------- Colocar os dados de cada bit de 8 bits numa area de memoria separada -------- */
b4 = g[4]; b5 = g[5]; b6 = g[6]; b7 = g[7];
for (i = 0; i < altura; i++) /* LSP salva no b0 que codifica primeiro */ { for (j = 0; j < largura; j++) { *b0 <<= 1; *b0 |= (*k & 0x01); *k >>= 1; *b1 <<= 1; *b1 |= (*k & 0x01); *k >>= 1; *b2 <<= 1; *b2 |= (*k & 0x01); *k >>= 1; *b3 <<= 1; *b3 |= (*k & 0x01); *k >>= 1; *b4 <<= 1; *b4 |= (*k & 0x01); *k >>= 1; *b5 <<= 1; *b5 |= (*k & 0x01); *k >>= 1; *b6 <<= 1; *b6 |= (*k & 0x01); *k >>= 1; *b7 <<= 1; *b7 |= (*k & 0x01); if ((j & 7) == 7) { b0++; b1++; b2++; b3++;
Apêndice B 172
b4++; b5++; b6++; b7++; } k++; } } /* i */ return; } void MEM_R (unsigned char *ptr, unsigned int altura, unsigned int alta_byte, FILE *fpix, char *fe) {
tamanho = byte * altura;
}
fread (ptr, alta_byte * altura, sizeof(unsigned char), fpix); if (feof(fpix)) { fprintf (stderr, "Fim do arquivo de pixels '%s' inesperado !\n",fe); exit(1); } if (ferror(fpix) || fclose(fpix)) { fprintf (stderr,"Problema durante a leitura do arquivo '%s'\n",fe); exit(1); } return; } unsigned char *reserva_char (unsigned int byte, unsigned int altura) /* -------- Reservando uma area com valores zeros nela -------- */ { unsigned int tamanho; unsigned char *ptr_p;
ptr_p = (unsigned char *) calloc(tamanho, sizeof(unsigned char)); if (!ptr_p) { fprintf (stderr, " Nao tem memoria suficiente !!!!!!!!!!\n"); exit(1); } return (ptr_p);
unsigned int lerint (FILE *fpix) { unsigned int i, c; if ((c = getc(fpix)) != EOF) { ungetc(c, fpix); fscanf(fpix,"%d",&i); } return i; }
Apêndice B 173
FILE *ABRIR (char *f, FILE *PCT) { FILE *fpix; unsigned int k; unsigned char L, tipo; fpix = fopen(f,"rb"); if (!fpix) { fprintf (stderr,"Nao pode abrir o arquivo de pixels '%s'\n",f); exit(1); } if ((L = getc(fpix)) != 'P') { fprintf (stderr," O arquivo '%s' nao e tipo PPM !\n",f); exit(1); } fwrite (&L, 1, sizeof(unsigned char), PCT); if ((tipo = getc(fpix)) != '6') { fprintf (stderr,"O arquivo '%s' nao e com formato RAW de tipo PPM !\n",f); exit(1); } fwrite (&tipo, 1, sizeof(unsigned char), PCT); fprintf (PCT,"\n"); while ((k = getc(fpix)) != EOF && !isdigit(k)) if (k =='#') { ungetc(k, fpix); while ((k = getc(fpix)) != EOF && !(k == 13 || k == 10)) fprintf (PCT,"%c",k); fprintf (PCT,"\n"); } ungetc(k, fpix); return (fpix); } void CAMADAS (struct code_estado *s, char *fs, char *fe) { FILE *fpix, *PCT; unsigned char *area, **PLANO, h; unsigned int espaco, DL, D, NO_PLANO, liga, PT, m; unsigned int largura, altura, nivel, nova_lar, lar; unsigned char *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7; PCT = fopen(fs,"wb"); if (!PCT) { fprintf (stderr,"Nao pode abrir o arquivo '%s' de saida\n",fs); exit(1); } fpix = ABRIR (fe, PCT); printf ("\n\n ========>> ATENCAO! ... O numero de PLANOS = 8 \n\n");
Apêndice B 174
NO_PLANO = 8; DL = 0;
C: printf ("\n\n =========>> Entre com numeros de Camadas de Resolucao = ");
somente a camada de resolucao total .... \n\n");
printf ("\n\n ===> Digite 1 para ativar processo da Predição Tipical = "); scanf ("%d",&PT); if (PT == 1) printf ("\n ---- Codificaco Progressiva Com a Opcao PT ----\n"); else printf ("\n ---- Codificaco Progressiva sem Usar a Opcao PT ----\n");
scanf ("%d",&D); if (D > 7 || D == 0) { printf ("\n O padrao JBIG ADEVERTE! o valor de camadas deveria ser \ entre (1) e (7). ===> Por favor, repeta-se o processo ... \n\n"); goto C; } printf("\n\n ATENCAO! ... A codificacao feita em cada PLANO para \
espaco = 0; largura = lerint (fpix) * 3; /*- pois temos RGB(3 bandas) in cada pixel -*/ altura = lerint (fpix); h = getc(fpix); nivel = lerint (fpix); h = getc(fpix); /* ----- Colocar os dados da imagem original numa area ----- */ area = reserva_char (largura, altura); MEM_R (area, altura, largura, fpix, fe); /* ------ Reservar uma area para cada bit de pixel (8 bits) da imagem original ----- */ PLANO = (unsigned char **) calloc(NO_PLANO, sizeof(unsigned char)); if (!PLANO) { fprintf (stderr, "Nao tem memoria suficiente para a reserva!\n"); exit(1); } lar = largura / 8; /*-- Medida nova para nova area de cada bit (PLANO) --*/ for (m = 0; m < NO_PLANO; m++) PLANO[m] = reserva_char (lar, altura); /* - Colocar os dados de cada bit de cada byte separados na memoria - */ t0 = PLANO[0]; t1 = PLANO[1]; t2 = PLANO[2]; t3 = PLANO[3]; t4 = PLANO[4]; t5 = PLANO[5]; t6 = PLANO[6]; t7 = PLANO[7]; PLANO_P (largura, altura, area, PLANO); free (area); fprintf (PCT,"%d", DL); fprintf (PCT,"%d", D); fprintf (PCT,"%d", NO_PLANO); fprintf (PCT,"%d", espaco); fprintf (PCT," %d %d ", largura/3, altura); /* Divide por 3 pois o cabeçalho */ fprintf (PCT,"%d ", nivel); printf ("\n Modelo Template de Baixa Res. : - Duas linhas => digite 2:"); printf ("\n - Tres linhas => digite 3:"); scanf ("%d",&liga); fprintf(PCT,"%d",liga); fprintf (PCT,"%d", PT); nova_lar = lar * 8; /* -- # de bits por linha em cada PLANO = largura -- */ DIVIDE (s, nova_lar, altura, liga, PT, PCT, t0); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t1);
Apêndice B 175
DIVIDE (s, nova_lar, altura, liga, PT, PCT, t2); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t3); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t4); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t5); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t6); DIVIDE (s, nova_lar, altura, liga, PT, PCT, t7); FIMC (s, PCT); free(PLANO); if (ferror(PCT) || fclose(PCT)) { fprintf (stderr,"Problema durante escrever no arquivo '%s'\n",fs); exit(1); } return; } void INITC (struct code_estado *s) { int i; for (i = 0; i < 4096; s->ST[i++] = 0); s->C = 0; s->A = 0x10000; s->SC = 0; s->CT = 11; s->BUF = -1; /* buffer vazio */ return; } main (argc, argv) char *argv[];
struct code_estado s;
{
char *fe = argv[1], *fs = argv[2]; if ((fe != NULL) && (fs != NULL)) { INITC (&s); CAMADAS (&s, fs, fe); printf (" \n\n...... FIM DO PROCESSO DE CODIFICACAO ......\n\n"); } else printf ("'erro'! \n\n Por favor, entre com: nome do arquivo tipo PPM \ e da saida para armazenar os dados compactados, sequencialmente.\n"); } /* main */
Apêndice B 176
/* ---- Utilizando imagem (colorida) de formato ROW tipo PGM decodificando ---- */ /* ---- a alta camada de resolução de cada plano e construir as camadas diferenciais ----- */
{
/* --------------------- com a opção de usar o processo de Predição Típica --------------------- */ #include <stdio.h> #include <ctype.h> #include <assert.h> #include <stdlib.h> #include "tabela.h" #define MARKER_STUFF 0X00 #define MARKER_SDNORM 0X02 #define MARKER_SDRST 0X03 #define MARKER_ESC 0XFF #define PTB2CX 0X195 #define PTB3CX 0X0E5 /* ------ Descricao "status" de decodificador aritmetico ----- */
struct decode_estado
unsigned char ST[4096]; /* "status" prob. dos contextos, e MSB = MPS */ unsigned int C; /* registrador C, base de intervalo a ser codificado*/ int A; /* registrador A, tamanho normalizado de intervalo */ int CT; /* contador de dislocamento de bits, determina * * quando pro'ximo byte vai ser lido */ int lnpt; /* flag de PT: linha nao e' Predicao Tipical */ };
void LERBYTE (struct decode_estado *s, FILE *PCT) { unsigned int k; L: if ((k = getc(PCT)) != EOF) { if (k == MARKER_ESC) { if ((k = getc(PCT)) == EOF) { printf ("\n Erro! No codigo do Encerramento, surgeu 0xff extra!\n"); exit(1); } else if (k == MARKER_SDNORM) goto L; else if (k == MARKER_SDRST) { printf ("\n O fim dos dados da camada, encerramento reforcado \n"); goto L; /* --- passa = No. da camada onde foi o encerramento --- */
Apêndice B 177
} else if (k == MARKER_STUFF) k = 0xff; else {
}
{
printf ("\n Erro! Nao ha codigo de STUFF \n\n"); exit(1);
} } else k = 0; s->C |= k << 8; s->CT = 8; return; } void RENORMDEC (struct decode_estado *s, FILE *PCT) { do
if (s->CT == 0) LERBYTE (s, PCT); s->C <<= 1; s->A <<= 1; --s->CT; } while (s->A < 0x8000); if (s->CT == 0) LERBYTE (s, PCT); return; } unsigned int DECODIF (struct decode_estado *s, FILE *PCT, unsigned short CX) { unsigned int PIX; extern short LSZ[]; register int lsz, ss; register unsigned char *st; extern char NMPS[], NLPS[], SWTCH[]; ss = s->ST[CX] & 0x7f; /* determina o estado do contexto CX */ assert (ss < 113); lsz = LSZ[ss]; /* consulta a estimativa de probabilidade relativa ao estado do CX */ if ((s->C >> 16) < (s->A -= lsz)) if (s->A >= 0x8000) { PIX = s->ST[CX] >> 7; return PIX; } else /* ----------- MPSDECODIF ----------- */ if (s->A < lsz)
Apêndice B 178
{
{
PIX = 1 - (s->ST[CX] >> 7); /* --- teste se a troca condicional (MPS/LPS) e' necessa ria --- */ if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* XOR para invertir o valor de MVAL[CX] */ /* - escolha o proximo estado de estimativa de probabilidade - */ s->ST[CX] &= 0x80; s->ST[CX] |= NLPS[ss]; } else
PIX = s->ST[CX] >> 7; s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } else /* ----------- LPSDECODIF ----------- */ if (s->A < lsz) { s->C -= s->A << 16; s->A = lsz; PIX = s->ST[CX] >> 7; s->ST[CX] &= 0x80; s->ST[CX] |= NMPS[ss]; } else { s->C -= s->A << 16; s->A = lsz; PIX = 1 - (s->ST[CX] >> 7); /* --- teste se a troca condicional (MPS/LPS) e necessaria --- */ if (SWTCH[ss]) s->ST[CX] ^= 0x80; /* XOR para invertir o valor de MVAL[CX] */ /* - escolha o proximo estado de estimativa de probabilidade - */ s->ST[CX] &= 0x80; s->ST[CX] |= NLPS[ss]; } RENORMDEC (s, PCT); return PIX; } void DCOD6 (struct decode_estado *s, unsigned char *Res_bit, unsigned int largura, unsigned int altura, unsigned int alta_byte, unsigned int liga, unsigned int PTBON, FILE *PCT) { unsigned int i, j, CX_CBR, SLNPT; unsigned int cx, PIX, fase1, fase2; unsigned char *lp1, *lp2, *p1, *q1; register unsigned int linha_h1,linha_h2,linha_h3,linha_l1,linha_l2,linha_l3; /*** codificar somente a camada total de cada Plano ou seja codificacao quando camada = 0 ***/
Apêndice B 179
cx = 0; PIX = 0;
} /* else */
linha_h3 |= *(lp2 - alta_byte - alta_byte + 1);
s->lnpt = 1; lp2 = Res_bit; lp1 = lp2 + alta_byte; for (i = 0; i < altura; i++) { /* =============== Predição Tipical =============== */ if (PTBON == 1) { if (liga == 2) CX_CBR = 1; else CX_CBR = 0; SLNPT = DECODIF (s, PCT, CX_CBR ? PTB2CX : PTB3CX); s->lnpt = !(SLNPT ^ s->lnpt); /** se A=B entao A.XOR.B=0 **/ if (!s->lnpt) { /* linha tipical (iqual a linha em cima dela) */ p1 = lp2; if (i == 0) while (p1 < lp2 + alta_byte) *p1++ = 0; else { q1 = lp2 - alta_byte; while (q1 < lp2) *p1++ = *q1++;
lp2 += alta_byte; continue; } /* if */ } /* if PTBON */ linha_h1 = linha_h2 = linha_h3 = 0; if (i > 0) { linha_h2 = (unsigned int) *(lp2 - alta_byte) << 8; if (i > 1 && liga == 3) linha_h3 = (unsigned int) *(lp2 - alta_byte - alta_byte) << 8; } /**** decodificacao da linha ****/ for (j = 0; j < largura;) { if ((j & 7) == 0) if ((j < (alta_byte * 8 - 8)) && (i > 0)) { linha_h2 |= *(lp2 - alta_byte + 1); if (i > 1 && liga == 3)
} do { switch (liga) {
Apêndice B 180
case 2: /* template de duas linhas */ cx = (linha_h1 & 0x00f) + ((linha_h2 >> 9) & 0x3f0); break; case 3: /* template de tres linhas */ cx = (linha_h1 & 0x003) + ((linha_h2 >> 11) & 0x07c) + ((linha_h3 >> 7) & 0x380); linha_h3 <<= 1; break; default: fprintf (stderr,"Tipo de Template -%d- errado!\n" ,liga); exit(1); } PIX = DECODIF (s, PCT, cx); cx = 0; linha_h1 <<= 1; linha_h1 |= (PIX & 1); linha_h2 <<= 1; } while (++j & 7 && j < largura); *lp2 = linha_h1; lp2++; } /* j */ *(lp2 - 1) <<= alta_byte * 8 - largura; } /* i */ return; } void MEM_W (unsigned char *bit, unsigned int altura, unsigned int alta_byte, FILE *pix_final, char fn[]) { fwrite (bit, alta_byte * altura, sizeof(unsigned char), pix_final); if (ferror(pix_final) || fclose(pix_final)) { fprintf (stderr,"Problema no escrito dos pixels em '%s'\n",fn); exit(1); } return; } unsigned char *reserva_char (unsigned int byte, unsigned int altura) /* -------- Reservando uma area com valores zeros nela -------- */ { unsigned int tamanho; unsigned char *ptr_p; tamanho = byte * altura; ptr_p = (unsigned char *) calloc(tamanho, sizeof(unsigned char)); if (!ptr_p) { fprintf(stderr, "Nao tem memoria suficiente para os pixels!\n"); exit(1); } return (ptr_p); }
Apêndice B 181
unsigned int TAMANHO (unsigned int largura) { unsigned int MOD, tamanho; /* --------- No. de pixels por linha ----------- */ MOD = largura % 8; if (MOD) tamanho = largura + (8 - MOD); else tamanho = largura; return (tamanho); } unsigned int TAM_IN_BYTE (unsigned int largura) { unsigned int byte, tamanho_largura; /* ------- No. de bytes por linha ------- */ tamanho_largura = TAMANHO (largura); byte = tamanho_largura / 8; return (byte); } void INITD (struct decode_estado *s, FILE *PCT) { int i; for (i = 0; i < 4096; s->ST[i++] = 0); s->CT = 0; s->C = 0; LERBYTE (s, PCT); s->C <<= 8; LERBYTE (s, PCT); s->C <<= 8;
/************* um bit para reseber proximos dados de outros planos *************/
LERBYTE (s, PCT); s->A = 0x10000; return; } void plano (unsigned char *t, unsigned char *ptr, unsigned char *orig, unsigned int bytes, unsigned int alt) { unsigned int i, j, k; unsigned char *q, *p; /** colocar os dados da area t na area ptr (cada byte de t colocado em 8 bytes de ptr) **/ /** e tambem coloca-los na area orig de mesmo jeito de ptr, e cada byte e' deslocado **/
q = ptr; p = orig; for (i = 0; i < alt; i++) { for (j = 0; j < bytes; j++) { for (k = 0; k < 8; k++) {
Apêndice B 182
*q >>= 1; *q |= (*t & 0x80); q++; *p >>= 1; *p |= (*t & 0x80); p++; *t <<= 1; } t++; } } /* i */ return; } unsigned int x[20]; void SAIDA (unsigned char **bit, unsigned char *orig, unsigned int i, unsigned int nivel, unsigned int D, char fn[]) { FILE *pix_final; unsigned char *ptr; unsigned int cnt, ca, alta_byte; cnt = 0; ptr = reserva_char (x[cnt], x[cnt+1]); /*** onde x[cnt] = largura ***/ alta_byte = TAM_IN_BYTE (x[cnt]); /*** e x[cnt+1] = altura ***/ /*** criar a alta camada de cada plano e salva-la num arquivo ***/ plano (bit[0], ptr, orig, alta_byte, x[cnt+1]); sprintf(fn,"PLANO[%d]-D%d.ppm", i, D-1); pix_final = fopen(fn,"wb"); if (!pix_final) { fprintf (stderr,"Nao pode abrir o arquivo '%s' para escrever\n",fn); exit(1); } fprintf (pix_final,"%c%c\n", 'P', '6'); /* largura/3 so' na cabecalho */ fprintf (pix_final,"%d %d\n%d\n", x[cnt]/3, x[cnt+1], nivel); MEM_W (ptr, x[cnt+1], x[cnt], pix_final, fn); free (ptr); return; } void REDUZIR (unsigned char **bit, unsigned char *pln, unsigned int D, unsigned int nova_lar, unsigned int altura) { extern char Map[]; unsigned char *Meio, *F, *Pr, *P_baixa; unsigned int cnt, chave, ca, i, j, Resultado, cont_a, cont_b; unsigned short linha_F, linha_Meio, linha_Pr, linha_baixa2, baixa_pix; unsigned int baixa_nova_lar, baixa_altura, alta_byte, baixa_byte, baixa_L_tamanho; cnt = 0;
Apêndice B 183
chave = 1; for (ca = 1; ca < D; ca++) { if (chave != 0) { x[cnt] = nova_lar; cnt += 1; x[cnt] = altura; alta_byte = TAM_IN_BYTE (nova_lar); bit[ca-1] = pln;
cnt += 1;
/* Ponha-se os pixels da camada de baixa Resolucao a partir da mesma e de camada de alta Resolucao */
linha_F = linha_Meio = linha_Pr = linha_baixa2 = 0;
{
chave = 0; } Meio = bit[ca-1]; F = Meio - alta_byte; Pr = Meio + alta_byte; baixa_nova_lar = (nova_lar + 1)/2; baixa_altura = (altura + 1)/2;
x[cnt] = baixa_nova_lar; cnt += 1; x[cnt] = baixa_altura; baixa_L_tamanho = TAMANHO (baixa_nova_lar); baixa_byte = baixa_L_tamanho / 8; bit[ca] = reserva_char (baixa_byte, baixa_altura); P_baixa = bit[ca];
for (i = 0; i < baixa_altura; i++) { if (2 * i + 1 >= altura) Pr = Meio; /* -- para repetir ultima linha da imagem no final -- */ baixa_pix = 0;
for (j = 0; j < baixa_L_tamanho; j += 8)
*P_baixa = 0; linha_baixa2 |= i ? *(P_baixa - baixa_byte) : 0; /* --- linha_baixa2 = 0 caso i=0, e caso contrario pega --- */ /* --- o byte que esta a cima do byte atual do P_baixa --- */ for (cont_b=0; cont_b < 8 && j+cont_b < baixa_nova_lar; cont_b += 4) { if (((j + cont_b) >> 2) < alta_byte) { /* --- p/ evitar passar o limite de bytes na alta Res. --- */ linha_F |= i ? *F : 0; ++F; linha_Meio |= *Meio; ++Meio; linha_Pr |= *Pr; ++Pr; } for(cont_a=0;cont_a<4 && j+cont_b+cont_a<baixa_nova_lar; cont_a++) { linha_Pr <<= 2;
Apêndice B 184
linha_Meio <<= 2; linha_F <<= 2; linha_baixa2 <<= 1; Resultado = 0; Resultado = (((linha_Pr>>8) & 0x0007)+((linha_Meio>>5)& 0x0038) + ((linha_F >> 2) & 0x01c0) + (baixa_pix << 9) + ((linha_baixa2 << 2) & 0x0c00)); assert (Resultado >= 0 && Resultado < 4096); baixa_pix = 0; baixa_pix = Map[Resultado]; *P_baixa <<= 1; *P_baixa |= (unsigned char) baixa_pix; /** P_baixa e linha atual na baixa Res. **/ } /* --- baixa_pix e linha a cima do pixel ? estimado --- */ } ++P_baixa; } /* j */ /* ----- inserir bits de valores zeros no final de cada linha ----- */ /* ----- ate atengir ao tamanho de baixa_L_tamanho ----- */ *(P_baixa - 1) <<= baixa_L_tamanho - baixa_nova_lar;/** recua P_baixa */ F += alta_byte; /* para um byte ai colocand 0's nas digitos de byte */ Meio += alta_byte; Pr += alta_byte; /* pula 1 line p/ repetir o processo na 3 e 4 linha */ } /* i */ nova_lar = baixa_nova_lar; altura = baixa_altura; alta_byte = baixa_byte; } /* ca */ return; } void DIVIDE (struct decode_estado *s, FILE *PCT, char fn[]) { FILE *pix_final; unsigned char L, *pln, *orig, **bit; unsigned int largura, altura, alta_byte; unsigned int i, DL, D, NO_PLANO, espaco, PT, nivel, liga; while ((L = getc(PCT)) != EOF && !isdigit(L)) if (L =='#') { ungetc(L, PCT); while ((L = getc(PCT)) != EOF && !(L == 13 || L == 10)); } ungetc(L, PCT); fscanf (PCT,"%1d%1d%1d%1d%d%d%d%1d%d",&DL,&D,&NO_PLANO,&espaco,&largura,&altura,&nivel,&liga,&PT); largura = largura * 3; /* -- pois temos RGB (3 bandas) in cada pixel -- */ if (D == 1) printf("\n\n A decodificacao ser feita em cada PLANO para somente \ a camada de resolucao total \n\n");
Apêndice B 185
INITD (s, PCT); bit = (unsigned char **) calloc(D, sizeof(unsigned char)); if (!bit) { fprintf (stderr, "Nao tem memoria suficiente para a reserva!\n"); exit(1);
exit(1);
if ((L = getc(PCT)) != 'P')
exit(1);
if ((tipo = getc(PCT)) != '6')
} orig = reserva_char (largura, altura); alta_byte = TAM_IN_BYTE (largura); for (i = 0; i < NO_PLANO; i++) { pln = reserva_char (alta_byte, altura); DCOD6 (s, pln, largura, altura, alta_byte, liga, PT, PCT); REDUZIR (bit, pln, D, largura, altura); /* criar camadas diferenciais */ SAIDA (bit, orig, i, nivel, D, fn); /* salvar as camadas em arquivos */ free (pln); } /* i (PLANO) */ sprintf(fn,"imagem_orig.ppm"); pix_final = fopen(fn,"wb"); if (!pix_final) { fprintf (stderr,"Nao pode abrir o arquivo '%s' para escrever\n",fn); exit(1); } fprintf (pix_final,"%c%c\n", 'P', '6'); /* largura/3 so' na cabecalho */ fprintf (pix_final,"%d %d\n%d\n", largura/3, altura, nivel); MEM_W (orig, altura, largura, pix_final, fn); free (orig); free (bit); return; } void CAMADAS (struct decode_estado *s, char *fe) { FILE *PCT; char fn[20]; unsigned char tipo, L; PCT = fopen(fe,"rb"); if (!PCT) { fprintf (stderr," Nao pode abrir o arquivo '%s' para ler\n",fe);
}
{ fprintf (stderr,"O arquivo '%s' nao e tipo PPM !\n",fe);
}
{ fprintf (stderr,"O arquivo '%s' nao e com formato RAW de tipo PGM !\n",fe); exit(1);
Apêndice B 186
} DIVIDE (s, PCT, fn); if (ferror(PCT) || fclose(PCT)) { fprintf (stderr,"Problema durante lendo os pixels de '%s'\n",fe); exit(1); } return; } main(argc, argv) char *argv[]; { char *fe = argv[1]; struct decode_estado s; if (fe != NULL) { CAMADAS (&s, fe); printf ("\n\n ........ FIM DO PROCESSO DE DECODIFICACAO ........\n\n");
} else printf ("\n\n ---> 'erro'! Por favor, \n\n \ somente, entre com nome do arquivo compactado.\n\n"); } /* main */
Referências Bibliográficas 187
REFERÊNCIAS BIBLIOGRÁFICAS
[1] Robertson, G. R., Aburdene, M. F., and Kozick, R. J., “Differential Block Coding of
Bilevel Images”, IEEE Trans. On Image Processing, Vol. 5, No. 9, pp. 1368-1370,
September 1996.
[2] CCITT Rec. T.82 | ISO/IEC 11544 (JBIG), “Information Technology – Coded
Representation of Picture and Audio Information – Progressive Bi-level Images
Compression”, 1993.
[3] Jain, A. K., “Image Data Compression: A Review”, Proc. of the IEEE, Vol. 69, No. 3,
1981.
[4] Held, G., “Compressão de Dados Técnicas e Aplicações Considerações de
Hardware e Software”, Érica, São Paulo, 1992.
[5] Langdon, G. G. Jr., “An Introduction to Arithmetic Coding”, IBM Journal of Research
and Development, Vol. 28, No. 2, pp. 135-149, March 1984.
[6] Gonzalez, R. C., Woods, R. E., “Digital Image Processing”, Addison-Wesley
Publishing Company Inc., September 1993.
[7] Kalifa, E. A., Yabu-uti, J., “Codificação e Decodificação de Arquivos de Fac-símile
G3/CCITT”, M.Sc. Dissertação, Departamento de Comunicações, Faculdade de
Engenharia Elétrica e de Computação, UNICAMP, Campinas - SP - Brasil, Outubro
1994.
[8] Shannon, C. E., “The Mathematical Theory of Communication”, Parts I and II, Bell
System Technology J., Vol. 27, pp. 379-423 and 623-656, July 1948.
Referências Bibliográficas 188
[9] Hampel, H., et al., “Technical Features of The JBIG Standard for Progressive Bi-level
Image Compression”, Signal Processing: Image Communication 4, Vol. 4, No. 2,
April 1992.
[10] Ahmed Mohamed Abushaala, and Yuzo Iano, “Lossless Compression Coding of
Greyscale Images Based on JBIG Standard”, SPPRA 2002: IASTED International
Conference on Signal Processing, Pattern Recongnition, and Application, Crete,
Greece, pp. 339-341, June 25-28, 2002.
[11] Ahmed Mohamed Abushaala, “ISO/JBIG: Codificação Aritmética de Imagens em 2
tons”, M.Sc. Dissertação, Departamento de Comunicações, Faculdade de
Engenharia Elétrica e de Computação, UNICAMP, Campinas - SP - Brasil, Outubro
1996.
[12] Langdon, G. G. Jr., and Rissanen, J. J., “A Double-Adaptive File Compression
Algorithm”, IEEE Transactions On Communications, Vol. COM-31, No. 11, pp.
1253-1255, Nov. 1983.
[13] Lynch, T. J., “Data Compression Techniques and Application”, New York: Van
Nostrand Reinhold, 1985.
[14] Reavy, M. D., and Boncelet, C. G., “An Algorithm for Compression of Bilevel
Images”, IEEE Trans. On Image processing, Vol. 10, No. 5, pp. 669-676, May
2001.
[15] Martins, B., and Forchhammer, S.,“Lossless, Near-Lossless, and Refinement
Coding of Bilevel Images”, IEEE Trans. On Image Processing, Vol. 8, No. 5, May
1999.
[16] Bell, T. G., Cleary, J. G., and Witten, I. H.,“Text Compression”, Englewood Cliffs,
NJ: Prentice-Hall, 1990.
Referências Bibliográficas 189
[17] Witten, I. H., Neal, R. M., and Cleary, J. G.,“Arithmetic Coding for Data
Compression”, Comm. Of the ACM, Vol. 30, No. 6, June 1987.
[18] CCITT Rec. T.81 | ISO/IEC 10918-1 (JPEG), “Information Technology - Digital
Compression and Coding of Continuous – Tone Still Images” Requirements and
Guidelines, 1992.
[19] Schalkwijk, J. P. M., “An Algorithm for Source Coding”, IEEE Trans. Info. Theory,
Vol. IT-18, No. 3, pp. 395-399, May 1972.
[20] Rissanen, J. J., “Generalized Kraft Inequality and Arithmetic Coding”, IBM J. Res.
Develop., Vol. 20, pp. 198-203, May 1976.
[21] Pasco, R., “Source Coding Algorithms for Fast Data Compression”, Ph.D.
dissertation, Dept. of Elec. Eng., Stanford Univ., Stanford, CA, May 1976.
[22] Rissanen, J. J., and Langdon, G. G. Jr., “Arithmetic Coding”, IBM J. Res. Develop.,
Vol. 23, No. 2, pp. 149-162, May 1979.
[23] Jelinek, F., “Buffer Overflow in Variable Length of Coding of Fixed Rate Sources”,
IEEE Trans. Info. Theory, Vol. IT-14, pp. 490-501, May 1968.
[24] Abramson, N., “Information Theory and Coding”, New York: McGraw-Hill, 1963.
[25] Kuang, S., Jou, J., and Chen, Y., “The Design of an Adaptive On-Line Binary
Arithmetic-Coding Chip”, IEEE Trans. On Circuits and systems, Fundamental
Theory and Applications, Vol. 45, No. 7, pp. 693-706, July 1998.
[26] Ong, K., Chang, W., Tseng, Y., Lee, Y., and Lee, C., “A High Throughput Low Cost
Context-based Adaptive Arithmetic Codec for Multiple Standards”, IEEE ICIP 2002,
pp. I-872 – I-875, 2002.
[27] PGM – Portable Graymap File Format, ftp://ece.nwu.edu/pub/303/pgm.
[28] PPM – Portable Pixmap File Format, http://netpbm.sourceforge.net/doc/ppm.html.
Referências Bibliográficas 190
[29] Burk, P.,”Image Files”,http://astronomy.swin.edu.au/~pbourke/dataformats/ppm/
Trabalhos Realizados 191
Trabalhos Realizados 1- PUBLICAÇÕES EM CONGRESSOS E SIMPÓSIOS
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Coding of Bit-Plane Resolution Layer of Greyscale Images Based on
JBIG Standard”. VIIP 2002: IASTED International Conference on Visualization, Imaging, and Image
Processing. Benalmádena-Málaga, SPAIN, pp. 225-228, Setembro de 2002.
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Lossless Compression Coding of Greyscale Images Based on JBIG
Standard”. SPPRA 2002: IASTED International Conference on Signal Processing, Pattern Recognition, and
Application. Crete, GREECE, pp. 339-341, Junho de 2002.
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Relevant Aspects of Data Compression for Two-Tone Image Based
on JBIG Standard”. ICSPC'98: IASTED International Conference on Signal Processing and
Communications - Fundamentals of Image Processing, IEEE - Spanish Section, Canary Island, SPAIN,
Universidade de Las Palmas de Gran Canaria, pp. 147-150, Fevereiro de 1998.
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Implementation of Adaptive Binary Arithmetic Coding of JBIG
Standrad for Bi-level Image”. SBPN’97: Simpósio da 5o Reunião Annual de Sociedade Brasileira de
Pesquisadores Nikkeis de Ciência e Tecnologia, Ciência e Cultura na Globalização - Novas Paradigmas.
Majestic Hotel - Águas de Lindóia, São Paulo, BRASIL, pp. 122-128, Agosto de 1997.
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Software Development of the Adaptive Binary Arithmetic Coding of
JBIG Standard of Bi-level Image Compression”. SIE’97: Simpósio de Ingenieria Electrica – Electrónica y
Telecomunicaciones. Santa Clara, CUBA, Universidad Central de Las Villas, Ref. TEL-12, pp. 1-2, Junho de
1997.
2- PUBLICAÇÕES EM REVISTAS NACIONAIS
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Implementation of Adaptive Binary Arithmetic Coding of JBIG
Standard for Bi-level Image”. SBPN - Scientific Journal, Brazilian Society for Nikkei Researchers, ISSN
1415-6512, Vol. 2, No. 2, pp. 58-66, 1998.
Trabalhos Realizados
192
3- RELATÓRIOS TÉCNICOS
♦ Ahmed Mohamed Abushaala, Yuzo Iano. “Padrão JBIG/Norma ISO: Utilização da Codificação Aritmética
para Imagem Bi-level”. Contrato CPqD Telebrás 387/90 - PT 03, Processamento Digital Relatório Técnico -
249, PUB. FEEC 020/96, Campinas – SP - Brasil, Outubro de 1996.