Introdução
O WebP é um formato de imagem que usa (i) a codificação de frame-chave VP8 para compactar dados de imagem com perda ou (ii) a codificação WebP sem perda. Esses esquemas de codificação devem torná-lo mais eficiente do que formatos mais antigos, como JPEG, GIF e PNG. Ele é otimizado para transferência rápida de imagens pela rede (por exemplo, em sites). O formato WebP também tem paridade de recursos (perfil de cor, metadados, animação etc.) com outros formatos. Este documento descreve a estrutura de um arquivo WebP.
O contêiner WebP (ou seja, o contêiner RIFF para WebP) permite o suporte a recursos além do caso de uso básico do WebP (ou seja, um arquivo que contém uma única imagem codificada como um frame-chave VP8). O contêiner WebP oferece suporte adicional para:
Compressão sem perda: uma imagem pode ser compactada sem perdas usando o formato WebP Lossless.
Metadados: uma imagem pode ter metadados armazenados no formato de arquivo de imagem trocável (Exif) ou na plataforma de metadados extensível (XMP).
Transparência: uma imagem pode ter transparência, ou seja, um canal Alfa.
Perfil de cor: uma imagem pode ter um perfil ICC incorporado, conforme descrito pelo International Color Consortium.
Animação: uma imagem pode ter vários frames com pausas entre eles, tornando-a uma animação.
Nomeação
É RECOMENDADO usar os tipos abaixo ao se referir ao contêiner WebP:
Nome do formato do contêiner | WebP |
Extensão do nome de arquivo | .webp |
Tipo MIME | imagem/webp |
Identificador de tipo uniforme | org.webmproject.webp |
Terminologia e conceitos básicos
As palavras-chave "MUST" (precisa), "MUST NOT" (não pode), "REQUIRED" (obrigatório), "SHALL" (deve), "SHALL NOT" (não deve), "SHOULD" (deve), "SHOULD NOT" (não deve), "RECOMMENDED" (recomendado), "NOT RECOMMENDED" (não recomendado), "MAY" (pode) e "OPTIONAL" (opcional) neste documento devem ser interpretadas conforme descrito no BCP 14 RFC 2119 RFC 8174 quando, e somente quando, aparecerem em todas as maiúsculas, como mostrado aqui.
Um arquivo WebP contém uma imagem estática (ou seja, uma matriz codificada de pixels) ou uma animação. Opcionalmente, ele também pode conter informações de transparência, um perfil de cores e metadados. Nos referimos à matriz de pixels como a tela da imagem.
A numeração de bits em diagramas de partes começa em 0
para o bit mais significativo ('MSB 0'), conforme descrito na RFC 1166.
Confira abaixo outros termos usados neste documento:
- Leitor/gravador
- O código que lê arquivos WebP é chamado de leitor, enquanto o código que os grava é chamado de gravador.
- uint16
- Um número inteiro não assinado de 16 bits, little-endian.
- uint24
- Um número inteiro não assinado de 24 bits, little-endian.
- uint32
- Um número inteiro não assinado de 32 bits, little endian.
- FourCC
- Um código de quatro caracteres (FourCC) é um uint32 criado concatenando quatro caracteres ASCII na ordem little-endian. Isso significa que "aaaa" (0x61616161) e "AAAA" (0x41414141) são tratados como FourCCs diferentes.
- Baseado em 1
- Um campo de número inteiro sem sinal que armazena valores deslocados por
-1
. Por exemplo, esse campo armazenaria o valor 25 como 24. - ChunkHeader('ABCD')
- Usado para descrever o cabeçalho FourCC e Tamanho do bloco de blocos individuais, em que "ABCD" é o FourCC do bloco. O tamanho desse elemento é de 8 bytes.
Formato de arquivo RIFF
O formato de arquivo WebP é baseado no formato de documento RIFF (Resource Interchange File Format).
O elemento básico de um arquivo RIFF é um bloco. Ela consiste em:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk FourCC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Chunk Payload :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Chunk FourCC: 32 bits
- Código ASCII de quatro caracteres usado para identificação de partes.
- Tamanho da parte: 32 bits (uint32)
- O tamanho do bloco em bytes, sem incluir esse campo, o identificador do bloco ou o padding.
- Payload do bloco: Tamanho do bloco bytes
- O payload de dados. Se o Chunk size for ímpar, será adicionado um único byte de padding, que PRECISA ser
0
para estar em conformidade com o RIFF.
Observação: o RIFF tem uma convenção em que os pedaços FourCCs em maiúsculas são pedaços padrão que se aplicam a qualquer formato de arquivo RIFF, enquanto os FourCCs específicos de um formato de arquivo são todos em letras minúsculas. O WebP não segue essa convenção.
Cabeçalho de arquivo WebP
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'R' | 'I' | 'F' | 'F' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| File Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'W' | 'E' | 'B' | 'P' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 'RIFF': 32 bits
- Os caracteres ASCII 'R', 'I', 'F', 'F'.
- Tamanho do arquivo: 32 bits (uint32)
- O tamanho do arquivo em bytes, começando no deslocamento 8. O valor máximo desse campo é 2^32 menos 10 bytes. Portanto, o tamanho de todo o arquivo é, no máximo, 4 GiB menos 2 bytes.
- 'WEBP': 32 bits
- Os caracteres ASCII 'W', 'E', 'B', 'P'.
Um arquivo WebP PRECISA começar com um cabeçalho RIFF com o "WEBP" do FourCC. O tamanho do arquivo
no cabeçalho é o tamanho total dos blocos que seguem, mais 4
bytes para
o FourCC "WEBP". O arquivo NÃO DEVE conter dados depois dos especificados em Tamanho do arquivo. Os leitores PODEM analisar esses arquivos, ignorando os dados finais. Como o tamanho de qualquer fragmento é par, o tamanho fornecido pelo cabeçalho RIFF também é par. O conteúdo de cada bloco é descrito nas seções a seguir.
Formato de arquivo simples (com perda)
Esse layout DEVE ser usado se a imagem exigir codificação com perda e não exigir transparência ou outros recursos avançados fornecidos pelo formato estendido. Os arquivos com esse layout são menores e compatíveis com softwares mais antigos.
Formato de arquivo WebP simples (com perda):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: 'VP8 ' Chunk :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Pedaço "VP8":
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8 ') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8 data :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Dados VP8: Tamanho do bloco (bytes)
- Dados do fluxo de bits VP8.
O quarto caractere no FourCC "VP8" é um espaço ASCII (0x20).
A especificação do formato de bitstream VP8 é descrita no Guia de codificação e formato de dados VP8 (link em inglês). O cabeçalho do frame VP8 contém a largura e a altura do frame VP8. Isso é considerado a largura e a altura da tela.
A especificação VP8 descreve como decodificar a imagem no formato Y'CbCr. Para converter em RGB, Recommendation BT.601 DEVE ser usado. Os aplicativos podem usar outro método de conversão, mas os resultados visuais podem ser diferentes entre os decodificadores.
Formato de arquivo simples (sem perdas)
Observação: leitores mais antigos podem não oferecer suporte a arquivos com o formato lossless.
Esse layout DEVE ser usado se a imagem exigir codificação sem perdas (com um canal de transparência opcional) e não exigir recursos avançados fornecidos pelo formato estendido.
Formato de arquivo WebP simples (sem perdas):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: 'VP8L' Chunk :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Pedaço "VP8L":
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8L') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8L data :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Dados do VP8L: bytes do Chunk Size
- Dados do fluxo de bits VP8L.
A especificação atual do fluxo de bits VP8L pode ser encontrada em Formato de fluxo de bits sem perdas WebP. Observe que o cabeçalho do VP8L contém a largura e a altura da imagem do VP8L. Isso é considerado a largura e a altura da tela.
Formato de arquivo estendido
Observação: leitores mais antigos podem não oferecer suporte a arquivos com o formato estendido.
Um arquivo de formato estendido consiste em:
Um pedaço "VP8X" com informações sobre os recursos usados no arquivo.
Um bloco "ICCP" opcional com um perfil de cor.
Um bloco "ANIM" opcional com dados de controle de animação.
Dados da imagem.
Um bloco "EXIF" opcional com metadados Exif.
Um pedaço de "XMP" opcional com metadados XMP.
Uma lista opcional de fragmentos desconhecidos.
Para uma imagem estática, os dados da imagem consistem em um único frame, que é composto por:
Um subbloco Alfa opcional.
Para uma imagem animada, os dados da imagem consistem em vários frames. Mais detalhes sobre frames podem ser encontrados na seção Animação.
Todos os blocos necessários para reconstrução e correção de cores, ou seja, 'VP8X', 'ICCP', 'ANIM', 'ANMF', 'ALPH', 'VP8 ' e 'VP8L', precisam aparecer na ordem descrita anteriormente. Os leitores DEVEM falhar quando os pedaços necessários para a reconstrução e a correção de cor estiverem fora de ordem.
Metadados e blocos desconhecidos PODEm aparecer fora de ordem.
Motivo:os blocos necessários para a reconstrução precisam aparecer primeiro no arquivo para que um leitor possa começar a decodificar uma imagem antes de receber todos os dados. Um aplicativo pode se beneficiar de variar a ordem dos metadados e blocos personalizados para se adaptar à implementação.
Cabeçalho de arquivo WebP estendido:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8X') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv|I|L|E|X|A|R| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Canvas Width Minus One | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Canvas Height Minus One |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Reservado (Rsv): 2 bits
- PRECISA ser
0
. Os leitores PRECISAM ignorar esse campo. - Perfil ICC (I): 1 bit
- Define se o arquivo contém um bloco "ICCP".
- Alfa (L): 1 bit
- Define se algum dos frames da imagem contém informações de transparência ("alfa").
- Metadados Exif (E): 1 bit
- Define se o arquivo contém metadados Exif.
- Metadados XMP (X): 1 bit
- Define se o arquivo contém metadados XMP.
- Animação (A): 1 bit
- Defina se esta é uma imagem animada. Os dados nos blocos "ANIM" e "ANMF" precisam ser usados para controlar a animação.
- Reservado (R): 1 bit
- PRECISA ser
0
. Os leitores precisam ignorar esse campo. - Reservado: 24 bits
- PRECISA ser
0
. Os leitores PRECISAM ignorar esse campo. - Largura da tela menos um: 24 bits
- largura baseada em 1 da tela em pixels.
A largura real da tela é
1 + Canvas Width Minus One
. - Altura da tela menos um: 24 bits
- Altura baseada em 1 da tela em pixels.
A altura real da tela é
1 + Canvas Height Minus One
.
O produto de largura da tela e altura da tela PRECISA ser no máximo 2^32 - 1
.
Especificações futuras podem adicionar mais campos. Os campos desconhecidos PRECISAM ser ignorados.
Animação
Uma animação é controlada por blocos 'ANIM' e 'ANMF'.
Bloco 'ANIM':
Para uma imagem animada, esse bloco contém os parâmetros globais da animação.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANIM') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Background Color |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Loop Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Cor do plano de fundo: 32 bits (uint32)
- A cor de plano de fundo padrão da tela na ordem de bytes
[Blue, Green, Red, Alpha]. Essa cor PODE ser usada para preencher o espaço não utilizado na tela ao redor dos frames, bem como os pixels transparentes do primeiro frame.
A cor de plano de fundo também é usada quando o método de descarte é
1
.
Observações:
A cor de plano de fundo PODE conter um valor alfa não opaco, mesmo que a flag Alpha no bloco 'VP8X' não esteja definida.
Os aplicativos de visualização precisam tratar o valor da cor de plano de fundo como uma dica e não precisam usá-lo.
O canvas é apagado no início de cada loop. A cor de fundo PODE ser usada para fazer isso.
- Contagem de loops: 16 bits (uint16)
- O número de vezes que a animação será repetida. Se for
0
, isso significa infinitamente.
Esse bloco PRECISA aparecer se a flag Animation no bloco "VP8X" estiver definida. Se a flag Animation não estiver definida e esse bloco estiver presente, ele PRECISA ser ignorado.
Pedaço "ANMF":
Para imagens animadas, esse bloco contém informações sobre um único frame. Se a sinalização de animação não estiver definida, esse bloco NÃO DEVE estar presente.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANMF') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame X | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Frame Y | Frame Width Minus One ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... | Frame Height Minus One |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Duration | Reserved |B|D|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Frame Data :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Frame X: 24 bits (uint24)
- A coordenada X do canto superior esquerdo do frame é
Frame X * 2
. - Frame Y: 24 bits (uint24)
- A coordenada Y do canto superior esquerdo do frame é
Frame Y * 2
. - Largura do frame menos um: 24 bits (uint24).
- A largura baseada em 1 do frame.
A largura do frame é
1 + Frame Width Minus One
. - Frame height minus one: 24 bits (uint24)
- A altura baseada em 1 do frame.
A altura do frame é
1 + Frame Height Minus One
. - Duração do frame: 24 bits (uint24)
- O tempo de espera antes de mostrar o próximo frame, em unidades de 1 milissegundo. A interpretação da duração do frame de 0 (e geralmente <= 10) é definida pela implementação. Muitas ferramentas e navegadores atribuem uma duração mínima semelhante ao GIF.
- Reservado: 6 bits
- PRECISA ser
0
. Os leitores PRECISAM ignorar esse campo. - Método de mistura (B): 1 bit
Indica como os pixels transparentes do frame atual precisam ser mesclados com os pixels correspondentes da tela anterior:
0
: use a combinação Alfa. Depois de descartar o frame anterior, renderize o frame atual na tela usando a mistura alfa (consulte abaixo). Se o frame atual não tiver um canal alfa, presuma que o valor alfa seja 255, substituindo o retângulo efetivamente.1
: não mesclar. Depois de descartar o frame anterior, renderize o frame atual na tela substituindo o retângulo coberto pelo frame atual.
- Método de descarte (D): 1 bit
Indica como o frame atual será tratado depois de ser exibido (antes de renderizar o próximo frame) na tela:
0
: não descarte. Deixe a tela como está.1
: descarta a cor de plano de fundo. Preencha o retângulo na tela coberto pelo frame atual com a cor de plano de fundo especificada no bloco "ANIM".
Observações:
A eliminação de frames só se aplica ao retângulo do frame, ou seja, o retângulo definido por Frame X, Frame Y, largura do frame e altura do frame. Ela pode ou não cobrir toda a tela.
Combinação alfa:
Considerando que cada um dos canais R, G, B e A tem 8 bits e que os canais RGB não são pré-multiplicados por Alfa, a fórmula para mesclar 'dst' em 'src' é:
blend.A = src.A + dst.A * (1 - src.A / 255) if blend.A = 0 then blend.RGB = 0 else blend.RGB = (src.RGB * src.A + dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
A mistura alfa PRECISA ser feita no espaço de cores linear, considerando o perfil de cores da imagem. Se o perfil de cor não estiver presente, o RGB padrão (sRGB) será usado. Observe que sRGB também precisa ser linearizado devido a uma gama de ~2,2.
- Dados do frame: tamanho do chunk bytes -
16
Consiste em:
Um subbloco alfa opcional para o frame.
Um subbloco de bitstream para o frame.
Uma lista opcional de fragmentos desconhecidos.
Observação: o payload "ANMF", Frame Data, consiste em blocos preenchidos individuais, conforme descrito pelo formato de arquivo RIFF.
Alfa
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ALPH') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv| P | F | C | Alpha Bitstream... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Reservado (Rsv): 2 bits
- PRECISA ser
0
. Os leitores PRECISAM ignorar esse campo. - Pré-processamento (P): 2 bits
Esses bits informativos são usados para sinalizar o pré-processamento que foi realizado durante a compactação. O decodificador pode usar essas informações para, por exemplo, pontilhar os valores ou suavizar os gradientes antes da exibição.
0
: sem pré-processamento.1
: redução de nível.
Os decodificadores não são obrigados a usar essas informações de forma específica.
- Método de filtragem (F): 2 bits
Os métodos de filtragem usados são descritos a seguir:
0
: nenhuma.1
: filtro horizontal.2
: filtro vertical.3
: filtro de gradiente.
Para cada pixel, a filtragem é realizada usando os seguintes cálculos.
Suponha que os valores alfa em torno da posição atual de X
sejam rotulados como:
C | B |
---+---+
A | X |
Procuramos calcular o valor alfa na posição X
. Primeiro, uma previsão é
feita dependendo do método de filtragem:
- Método
0
: predictor = 0 - Método
1
: preditor = A - Método
2
: predictor = B - Método
3
: preditor = clipe(A + B - C)
em que clip(v)
é igual a:
- 0 se v for menor que 0
- 255 se v > 255.
- v Caso contrário
O valor final é derivado pela adição do valor descompactado X
ao
previsor e pelo uso da aritmética módulo-256 para agrupar o intervalo [256..511] no intervalo [0..255]:
alpha = (predictor + X) % 256
Há casos especiais para as posições de pixel mais à esquerda e na parte superior. Por exemplo, o valor no canto superior esquerdo na localização (0, 0) usa 0 como o valor do preditor. Se esse não for seu caso, faça o seguinte:
- Para métodos de filtragem horizontal ou gradiente, os pixels mais à esquerda na posição (0, y) são previstos usando a posição (0, y-1) logo acima.
- Para métodos de filtragem vertical ou gradiente, os pixels da parte de cima na localização (x, 0) são previstos usando a localização (x-1, 0) à esquerda.
- Método de compactação (C): 2 bits
O método de compactação usado:
0
: sem compactação.1
: compactado usando o formato WebP sem perda.
- Bitstream Alfa: Tamanho do bloco bytes -
1
Bitstream alfa codificado.
Este bloco opcional contém dados alfa codificados para este frame. Um frame que contém um pedaço "VP8L" NÃO DEVE conter esse bloco.
Motivação: as informações de transparência já fazem parte do bloco 'VP8L'.
Os dados do canal Alfa são armazenados como dados brutos não compactados (quando o método de compactação é "0") ou compactados usando o formato sem perdas (quando o método de compactação é "1").
Dados brutos: consistem em uma sequência de bytes de comprimento = largura * altura, contendo todos os valores de transparência de 8 bits na ordem de verificação.
Compactação de formato sem perda: a sequência de bytes é um fluxo de imagem compactado (como descrito em "Formato Bitstream sem perdas do WebP") de dimensões implícitas "largura x altura". Ou seja, esse fluxo de imagens NÃO contém cabeçalhos que descrevem as dimensões da imagem.
Motivo: as dimensões já são conhecidas de outras fontes, portanto, armazená-las novamente seria redundante e propenso a erros.
Depois que o fluxo de imagens é decodificado em valores de cor Alfa, vermelho, verde e azul (ARGB), seguindo o processo descrito na especificação do formato sem perdas, as informações de transparência precisam ser extraídas do canal verde do quadruplo ARGB.
Motivo: o canal verde tem etapas de transformação extras na especificação, ao contrário dos outros canais, o que pode melhorar a compactação.
Bitstream (VP8/VP8L)
Esse bloco contém dados compactados de bitstream para um único frame.
Um bloco de bitstream pode ser (i) um bloco "VP8", usando "VP8" (observe o espaço do quarto caractere significativo) como FourCC, ou (ii) um bloco "VP8L", usando "VP8L" como FourCC.
Os formatos dos blocos "VP8" e "VP8L" são descritos nas seções Formato de arquivo simples (com perda) e Formato de arquivo simples (sem perda), respectivamente.
Perfil de cor
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ICCP') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Color Profile :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Perfil de cores: bytes Chunk Size
- Perfil ICC.
Esse bloco PRECISA aparecer antes dos dados da imagem.
DEVE haver no máximo um bloco desse tipo. Se houver mais blocos desse tipo, os leitores poderão ignorar todos, exceto o primeiro. Consulte a especificação do ICC para mais detalhes.
Se esse bloco não estiver presente, o sRGB DEVE ser usado.
Metadados
Os metadados podem ser armazenados em blocos "EXIF" ou "XMP".
DEVE haver no máximo um pedaço de cada tipo ("EXIF" e "XMP"). Se houver mais blocos desse tipo, os leitores PODEM ignorar todos, exceto o primeiro.
Os blocos são definidos da seguinte maneira:
Bloco "EXIF":
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('EXIF') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Exif Metadata :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Metadados Exif: Tamanho do bloco (bytes)
- Metadados de imagem no formato Exif.
Pedaço "XMP":
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('XMP ') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: XMP Metadata :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Metadados XMP: Tamanho do bloco (bytes)
- Metadados de imagem no formato XMP.
O quarto caractere em "XMP '" FourCC é um espaço ASCII (0x20).
Confira mais orientações sobre o processamento de metadados nas "Diretrizes para o processamento de metadados" do Grupo de trabalho de metadados.
Partes desconhecidas
Um fragmento RIFF (descrito na seção Formato de arquivo RIFF) cujo FourCC é diferente de qualquer um dos fragmentos descritos neste documento é considerado um fragmento desconhecido.
Lógica: permitir blocos desconhecidos fornece uma provisão para extensão futura do formato e também permite o armazenamento de quaisquer dados específicos do aplicativo.
Um arquivo PODE conter blocos desconhecidos:
- no final do arquivo, conforme descrito na seção Cabeçalho de arquivo WebP estendido, ou
- no final de blocos "ANMF", conforme descrito na seção Animação.
Os leitores devem ignorar esses blocos. Os autores PRECISAM preservar esses blocos na ordem original, a menos que queiram modificar esses blocos.
Montagem de tela a partir de frames
Aqui, fornecemos uma visão geral de como um leitor PRECISA montar uma tela no caso de uma imagem animada.
O processo começa com a criação de uma tela usando as dimensões fornecidas no
bloco "VP8X", Canvas Width Minus One + 1
pixels de largura por Canvas Height Minus
One + 1
pixels de altura. O campo Loop Count
do bloco "ANIM" controla quantas
vezes o processo de animação é repetido. O valor é Loop Count - 1
para
valores Loop Count
diferentes de zero ou infinito se o Loop Count
for zero.
No início de cada iteração do loop, a tela é preenchida usando a cor de plano de fundo do bloco "ANIM" ou uma cor definida pelo aplicativo.
Os blocos 'ANMF' contêm frames individuais fornecidos na ordem de exibição. Antes de renderizar
cada frame, o Disposal method
do frame anterior é aplicado.
A renderização do frame decodificado começa nas coordenadas cartesianas (2 *
Frame X
, 2 * Frame Y
), usando o canto superior esquerdo da tela como a origem.
Frame Width Minus One + 1
pixels de largura por Frame Height Minus One + 1
pixels de altura são renderizados na tela usando Blending method
.
A tela é exibida por Frame Duration
milissegundos. Isso continua até que
todos os frames fornecidos por blocos "ANMF" sejam exibidos. Uma nova iteração de loop é
iniciada ou a tela é deixada no estado final se todas as iterações tiverem sido
concluídas.
O pseudocódigo a seguir ilustra o processo de renderização. A notação VP8X.field significa o campo no bloco "VP8X" com a mesma descrição.
VP8X.flags.hasAnimation MUST be TRUE
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
background color ANIM.background_color or
application-defined color.
loop_count ← ANIM.loopCount
dispose_method ← Dispose to background color
if loop_count == 0:
loop_count = ∞
frame_params ← nil
next chunk in image_data is ANMF MUST be TRUE
for loop = 0..loop_count - 1
clear canvas to ANIM.background_color or application-defined color
until eof or non-ANMF chunk
frame_params.frameX = Frame X
frame_params.frameY = Frame Y
frame_params.frameWidth = Frame Width Minus One + 1
frame_params.frameHeight = Frame Height Minus One + 1
frame_params.frameDuration = Frame Duration
frame_right = frame_params.frameX + frame_params.frameWidth
frame_bottom = frame_params.frameY + frame_params.frameHeight
VP8X.canvasWidth >= frame_right MUST be TRUE
VP8X.canvasHeight >= frame_bottom MUST be TRUE
for subchunk in 'Frame Data':
if subchunk.tag == "ALPH":
alpha subchunks not found in 'Frame Data' earlier MUST be
TRUE
frame_params.alpha = alpha_data
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
bitstream subchunks not found in 'Frame Data' earlier MUST
be TRUE
frame_params.bitstream = bitstream_data
apply dispose_method.
render frame with frame_params.alpha and frame_params.bitstream
on canvas with top-left corner at (frame_params.frameX,
frame_params.frameY), using Blending method
frame_params.blendingMethod.
canvas contains the decoded image.
Show the contents of the canvas for
frame_params.frameDuration * 1 ms.
dispose_method = frame_params.disposeMethod
Exemplos de layouts de arquivos
Uma imagem com codificação com perda e Alfa pode ser parecida com esta:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ALPH (alpha bitstream)
+- VP8 (bitstream)
Uma imagem codificada sem perdas pode ter a seguinte aparência:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- VP8L (lossless bitstream)
+- XYZW (unknown chunk)
Uma imagem sem perdas com um perfil ICC e metadados XMP pode ser semelhante a esta:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ICCP (color profile)
+- VP8L (lossless bitstream)
+- XMP (metadata)
Uma imagem animada com metadados Exif pode ter a seguinte aparência:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ANIM (global animation parameters)
+- ANMF (frame1 parameters + data)
+- ANMF (frame2 parameters + data)
+- ANMF (frame3 parameters + data)
+- ANMF (frame4 parameters + data)
+- EXIF (metadata)