bitstream update for lossy alpha compression

now, we only use 2 bits for the filtering method, and 2 bits
for the compression method.
There's two additional bits which are INFORMATIVE, to specify
whether the source has been pre-processed (level reduction)
during compression. This can be used at decompression time
for some post-processing (see DequantizeLevels()).

New relevant spec excerpt:

     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...                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Compression method (C): 2 bits

: The compression method used:

  * `0`: No compression.
  * `1`: Backward reference counts encoded with arithmetic encoder.

Filtering method (F): 2 bits

: The filtering method used:

  * `0`: None.
  * `1`: Horizontal filter.
  * `2`: Vertical filter.
  * `3`: Gradient filter.

Pre-processing (P): 2 bits

: These INFORMATIVE bits are used to signal the pre-processing that has
been performed during compression. The decoder can use this information to
e.g. dither the values or smooth the gradients prior to display.

  * `0`: no pre-processing
  * `1`: level reduction

Decoders are not required to use this information in any specified way.

Reserved (Rsv): 2 bits

: SHOULD be `0`.

Alpha bitstream: _Chunk Size_ - `1` bytes

: Encoded alpha bitstream.

This optional chunk contains encoded alpha data for a single tile.
Either **ALL or NONE** of the tiles must contain this chunk.

The alpha channel data is losslessly stored as raw data (when
compression method is '0') or compressed using the lossless format
(when the compression method is '1').

Change-Id: Ied8f5fb922707a953e6a2b601c69c73e552dda6b
This commit is contained in:
Pascal Massimino
2012-05-22 02:36:22 -07:00
parent d73e63a726
commit 638528cd1e
3 changed files with 69 additions and 33 deletions

View File

@ -13,15 +13,17 @@
#include "./vp8i.h"
#include "../webp/decode.h"
#include "../utils/filters.h"
#include "../utils/quant_levels.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
// TODO(skal): find a common place between enc/ and dec/ for these:
#define ALPHA_HEADER_LEN 2
#define ALPHA_HEADER_LEN 1
#define ALPHA_NO_COMPRESSION 0
#define ALPHA_LOSSLESS_COMPRESSION 1
#define ALPHA_PREPROCESSED_LEVELS 1
// TODO(skal): move to dsp/ ?
static void CopyPlane(const uint8_t* src, int src_stride,
@ -49,6 +51,8 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
const size_t decoded_size = height * width;
uint8_t* unfiltered_data = NULL;
WEBP_FILTER_TYPE filter;
int pre_processing;
int rsrv;
int ok = 0;
int method;
@ -59,12 +63,15 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
return 0;
}
method = data[0] & 0x0f;
filter = data[0] >> 4;
ok = (data[1] == 0);
method = (data[0] >> 0) & 0x03;
filter = (data[0] >> 2) & 0x03;
pre_processing = (data[0] >> 4) & 0x03;
rsrv = (data[0] >> 6) & 0x03;
if (method < ALPHA_NO_COMPRESSION ||
method > ALPHA_LOSSLESS_COMPRESSION ||
filter >= WEBP_FILTER_LAST || !ok) {
filter >= WEBP_FILTER_LAST ||
pre_processing > ALPHA_PREPROCESSED_LEVELS ||
rsrv != 0) {
return 0;
}
@ -91,15 +98,16 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
decoded_data[i] = (output[i] >> 8) & 0xff;
}
free(output);
ok = 1;
}
if (ok) {
WebPFilterFunc unfilter_func = WebPUnfilters[filter];
if (unfilter_func) {
if (unfilter_func != NULL) {
unfiltered_data = (uint8_t*)malloc(decoded_size);
if (unfiltered_data == NULL) {
if (method != ALPHA_NO_COMPRESSION) free(decoded_data);
return 0;
ok = 0;
goto Error;
}
// TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
// and apply filter per image-row.
@ -112,6 +120,11 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
CopyPlane(decoded_data, width, output, stride, width, height);
}
}
if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
ok = DequantizeLevels(decoded_data, width, height);
}
Error:
if (method != ALPHA_NO_COMPRESSION) {
free(decoded_data);
}