1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
10 // Alpha-plane decompression.
12 // Author: Skal (pascal.massimino@gmail.com)
18 #include "../utils/quant_levels_dec.h"
19 #include "../webp/format_constants.h"
21 //------------------------------------------------------------------------------
22 // ALPHDecoder object.
24 ALPHDecoder
* ALPHNew(void) {
25 ALPHDecoder
* const dec
= (ALPHDecoder
*)calloc(1, sizeof(*dec
));
29 void ALPHDelete(ALPHDecoder
* const dec
) {
31 VP8LDelete(dec
->vp8l_dec_
);
32 dec
->vp8l_dec_
= NULL
;
37 //------------------------------------------------------------------------------
40 // Initialize alpha decoding by parsing the alpha header and decoding the image
41 // header for alpha data stored using lossless compression.
42 // Returns false in case of error in alpha header (data too short, invalid
43 // compression method or filter, error in lossless header data etc).
44 static int ALPHInit(ALPHDecoder
* const dec
, const uint8_t* data
,
45 size_t data_size
, int width
, int height
, uint8_t* output
) {
47 const uint8_t* const alpha_data
= data
+ ALPHA_HEADER_LEN
;
48 const size_t alpha_data_size
= data_size
- ALPHA_HEADER_LEN
;
51 assert(width
> 0 && height
> 0);
52 assert(data
!= NULL
&& output
!= NULL
);
55 dec
->height_
= height
;
57 if (data_size
<= ALPHA_HEADER_LEN
) {
61 dec
->method_
= (data
[0] >> 0) & 0x03;
62 dec
->filter_
= (data
[0] >> 2) & 0x03;
63 dec
->pre_processing_
= (data
[0] >> 4) & 0x03;
64 rsrv
= (data
[0] >> 6) & 0x03;
65 if (dec
->method_
< ALPHA_NO_COMPRESSION
||
66 dec
->method_
> ALPHA_LOSSLESS_COMPRESSION
||
67 dec
->filter_
>= WEBP_FILTER_LAST
||
68 dec
->pre_processing_
> ALPHA_PREPROCESSED_LEVELS
||
73 if (dec
->method_
== ALPHA_NO_COMPRESSION
) {
74 const size_t alpha_decoded_size
= dec
->width_
* dec
->height_
;
75 ok
= (alpha_data_size
>= alpha_decoded_size
);
77 assert(dec
->method_
== ALPHA_LOSSLESS_COMPRESSION
);
78 ok
= VP8LDecodeAlphaHeader(dec
, alpha_data
, alpha_data_size
, output
);
83 // Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha
84 // starting from row number 'row'. It assumes that rows up to (row - 1) have
85 // already been decoded.
86 // Returns false in case of bitstream error.
87 static int ALPHDecode(VP8Decoder
* const dec
, int row
, int num_rows
) {
88 ALPHDecoder
* const alph_dec
= dec
->alph_dec_
;
89 const int width
= alph_dec
->width_
;
90 const int height
= alph_dec
->height_
;
91 WebPUnfilterFunc unfilter_func
= WebPUnfilters
[alph_dec
->filter_
];
92 uint8_t* const output
= dec
->alpha_plane_
;
93 if (alph_dec
->method_
== ALPHA_NO_COMPRESSION
) {
94 const size_t offset
= row
* width
;
95 const size_t num_pixels
= num_rows
* width
;
96 assert(dec
->alpha_data_size_
>= ALPHA_HEADER_LEN
+ offset
+ num_pixels
);
97 memcpy(dec
->alpha_plane_
+ offset
,
98 dec
->alpha_data_
+ ALPHA_HEADER_LEN
+ offset
, num_pixels
);
99 } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
100 assert(alph_dec
->vp8l_dec_
!= NULL
);
101 if (!VP8LDecodeAlphaImageStream(alph_dec
, row
+ num_rows
)) {
106 if (unfilter_func
!= NULL
) {
107 unfilter_func(width
, height
, width
, row
, num_rows
, output
);
110 if (alph_dec
->pre_processing_
== ALPHA_PREPROCESSED_LEVELS
) {
111 if (!DequantizeLevels(output
, width
, height
, row
, num_rows
)) {
116 if (row
+ num_rows
== dec
->pic_hdr_
.height_
) {
117 dec
->is_alpha_decoded_
= 1;
122 //------------------------------------------------------------------------------
125 const uint8_t* VP8DecompressAlphaRows(VP8Decoder
* const dec
,
126 int row
, int num_rows
) {
127 const int width
= dec
->pic_hdr_
.width_
;
128 const int height
= dec
->pic_hdr_
.height_
;
130 if (row
< 0 || num_rows
<= 0 || row
+ num_rows
> height
) {
131 return NULL
; // sanity check.
135 // Initialize decoding.
136 assert(dec
->alpha_plane_
!= NULL
);
137 dec
->alph_dec_
= ALPHNew();
138 if (dec
->alph_dec_
== NULL
) return NULL
;
139 if (!ALPHInit(dec
->alph_dec_
, dec
->alpha_data_
, dec
->alpha_data_size_
,
140 width
, height
, dec
->alpha_plane_
)) {
141 ALPHDelete(dec
->alph_dec_
);
142 dec
->alph_dec_
= NULL
;
147 if (!dec
->is_alpha_decoded_
) {
149 assert(dec
->alph_dec_
!= NULL
);
150 ok
= ALPHDecode(dec
, row
, num_rows
);
151 if (!ok
|| dec
->is_alpha_decoded_
) {
152 ALPHDelete(dec
->alph_dec_
);
153 dec
->alph_dec_
= NULL
;
155 if (!ok
) return NULL
; // Error.
158 // Return a pointer to the current decoded row.
159 return dec
->alpha_plane_
+ row
* width
;