1 // Copyright 2012 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 // main entry for the decoder
12 // Authors: Vikas Arora (vikaas.arora@gmail.com)
13 // Jyrki Alakuijala (jyrki@google.com)
19 #include "../dsp/lossless.h"
20 #include "../dsp/yuv.h"
21 #include "../utils/alpha_processing.h"
22 #include "../utils/huffman.h"
23 #include "../utils/utils.h"
25 #define NUM_ARGB_CACHE_ROWS 16
27 static const int kCodeLengthLiterals
= 16;
28 static const int kCodeLengthRepeatCode
= 16;
29 static const int kCodeLengthExtraBits
[3] = { 2, 3, 7 };
30 static const int kCodeLengthRepeatOffsets
[3] = { 3, 3, 11 };
32 // -----------------------------------------------------------------------------
33 // Five Huffman codes are used at each meta code:
34 // 1. green + length prefix codes + color cache codes,
38 // 5. distance prefix codes.
47 static const uint16_t kAlphabetSize
[HUFFMAN_CODES_PER_META_CODE
] = {
48 NUM_LITERAL_CODES
+ NUM_LENGTH_CODES
,
49 NUM_LITERAL_CODES
, NUM_LITERAL_CODES
, NUM_LITERAL_CODES
,
54 #define NUM_CODE_LENGTH_CODES 19
55 static const uint8_t kCodeLengthCodeOrder
[NUM_CODE_LENGTH_CODES
] = {
56 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
59 #define CODE_TO_PLANE_CODES 120
60 static const uint8_t kCodeToPlane
[CODE_TO_PLANE_CODES
] = {
61 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
62 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
63 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
64 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
65 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
66 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
67 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
68 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
69 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
70 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
71 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
72 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
75 static int DecodeImageStream(int xsize
, int ysize
,
77 VP8LDecoder
* const dec
,
78 uint32_t** const decoded_data
);
80 //------------------------------------------------------------------------------
82 int VP8LCheckSignature(const uint8_t* const data
, size_t size
) {
83 return (size
>= VP8L_FRAME_HEADER_SIZE
&&
84 data
[0] == VP8L_MAGIC_BYTE
&&
85 (data
[4] >> 5) == 0); // version
88 static int ReadImageInfo(VP8LBitReader
* const br
,
89 int* const width
, int* const height
,
90 int* const has_alpha
) {
91 if (VP8LReadBits(br
, 8) != VP8L_MAGIC_BYTE
) return 0;
92 *width
= VP8LReadBits(br
, VP8L_IMAGE_SIZE_BITS
) + 1;
93 *height
= VP8LReadBits(br
, VP8L_IMAGE_SIZE_BITS
) + 1;
94 *has_alpha
= VP8LReadBits(br
, 1);
95 if (VP8LReadBits(br
, VP8L_VERSION_BITS
) != 0) return 0;
99 int VP8LGetInfo(const uint8_t* data
, size_t data_size
,
100 int* const width
, int* const height
, int* const has_alpha
) {
101 if (data
== NULL
|| data_size
< VP8L_FRAME_HEADER_SIZE
) {
102 return 0; // not enough data
103 } else if (!VP8LCheckSignature(data
, data_size
)) {
104 return 0; // bad signature
108 VP8LInitBitReader(&br
, data
, data_size
);
109 if (!ReadImageInfo(&br
, &w
, &h
, &a
)) {
112 if (width
!= NULL
) *width
= w
;
113 if (height
!= NULL
) *height
= h
;
114 if (has_alpha
!= NULL
) *has_alpha
= a
;
119 //------------------------------------------------------------------------------
121 static WEBP_INLINE
int GetCopyDistance(int distance_symbol
,
122 VP8LBitReader
* const br
) {
123 int extra_bits
, offset
;
124 if (distance_symbol
< 4) {
125 return distance_symbol
+ 1;
127 extra_bits
= (distance_symbol
- 2) >> 1;
128 offset
= (2 + (distance_symbol
& 1)) << extra_bits
;
129 return offset
+ VP8LReadBits(br
, extra_bits
) + 1;
132 static WEBP_INLINE
int GetCopyLength(int length_symbol
,
133 VP8LBitReader
* const br
) {
134 // Length and distance prefixes are encoded the same way.
135 return GetCopyDistance(length_symbol
, br
);
138 static WEBP_INLINE
int PlaneCodeToDistance(int xsize
, int plane_code
) {
139 if (plane_code
> CODE_TO_PLANE_CODES
) {
140 return plane_code
- CODE_TO_PLANE_CODES
;
142 const int dist_code
= kCodeToPlane
[plane_code
- 1];
143 const int yoffset
= dist_code
>> 4;
144 const int xoffset
= 8 - (dist_code
& 0xf);
145 const int dist
= yoffset
* xsize
+ xoffset
;
146 return (dist
>= 1) ? dist
: 1; // dist<1 can happen if xsize is very small
150 //------------------------------------------------------------------------------
151 // Decodes the next Huffman code from bit-stream.
152 // FillBitWindow(br) needs to be called at minimum every second call
153 // to ReadSymbol, in order to pre-fetch enough bits.
154 static WEBP_INLINE
int ReadSymbol(const HuffmanTree
* tree
,
155 VP8LBitReader
* const br
) {
156 const HuffmanTreeNode
* node
= tree
->root_
;
157 uint32_t bits
= VP8LPrefetchBits(br
);
158 int bitpos
= br
->bit_pos_
;
159 // Check if we find the bit combination from the Huffman lookup table.
160 const int lut_ix
= bits
& (HUFF_LUT
- 1);
161 const int lut_bits
= tree
->lut_bits_
[lut_ix
];
162 if (lut_bits
<= HUFF_LUT_BITS
) {
163 VP8LSetBitPos(br
, bitpos
+ lut_bits
);
164 return tree
->lut_symbol_
[lut_ix
];
166 node
+= tree
->lut_jump_
[lut_ix
];
167 bitpos
+= HUFF_LUT_BITS
;
168 bits
>>= HUFF_LUT_BITS
;
170 // Decode the value from a binary tree.
171 assert(node
!= NULL
);
173 node
= HuffmanTreeNextNode(node
, bits
& 1);
176 } while (HuffmanTreeNodeIsNotLeaf(node
));
177 VP8LSetBitPos(br
, bitpos
);
178 return node
->symbol_
;
181 static int ReadHuffmanCodeLengths(
182 VP8LDecoder
* const dec
, const int* const code_length_code_lengths
,
183 int num_symbols
, int* const code_lengths
) {
185 VP8LBitReader
* const br
= &dec
->br_
;
188 int prev_code_len
= DEFAULT_CODE_LENGTH
;
191 if (!HuffmanTreeBuildImplicit(&tree
, code_length_code_lengths
,
192 NUM_CODE_LENGTH_CODES
)) {
193 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
197 if (VP8LReadBits(br
, 1)) { // use length
198 const int length_nbits
= 2 + 2 * VP8LReadBits(br
, 3);
199 max_symbol
= 2 + VP8LReadBits(br
, length_nbits
);
200 if (max_symbol
> num_symbols
) {
201 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
205 max_symbol
= num_symbols
;
209 while (symbol
< num_symbols
) {
211 if (max_symbol
-- == 0) break;
212 VP8LFillBitWindow(br
);
213 code_len
= ReadSymbol(&tree
, br
);
214 if (code_len
< kCodeLengthLiterals
) {
215 code_lengths
[symbol
++] = code_len
;
216 if (code_len
!= 0) prev_code_len
= code_len
;
218 const int use_prev
= (code_len
== kCodeLengthRepeatCode
);
219 const int slot
= code_len
- kCodeLengthLiterals
;
220 const int extra_bits
= kCodeLengthExtraBits
[slot
];
221 const int repeat_offset
= kCodeLengthRepeatOffsets
[slot
];
222 int repeat
= VP8LReadBits(br
, extra_bits
) + repeat_offset
;
223 if (symbol
+ repeat
> num_symbols
) {
224 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
227 const int length
= use_prev
? prev_code_len
: 0;
228 while (repeat
-- > 0) code_lengths
[symbol
++] = length
;
235 HuffmanTreeRelease(&tree
);
239 static int ReadHuffmanCode(int alphabet_size
, VP8LDecoder
* const dec
,
240 HuffmanTree
* const tree
) {
242 VP8LBitReader
* const br
= &dec
->br_
;
243 const int simple_code
= VP8LReadBits(br
, 1);
245 if (simple_code
) { // Read symbols, codes & code lengths directly.
249 const int num_symbols
= VP8LReadBits(br
, 1) + 1;
250 const int first_symbol_len_code
= VP8LReadBits(br
, 1);
251 // The first code is either 1 bit or 8 bit code.
252 symbols
[0] = VP8LReadBits(br
, (first_symbol_len_code
== 0) ? 1 : 8);
254 code_lengths
[0] = num_symbols
- 1;
255 // The second code (if present), is always 8 bit long.
256 if (num_symbols
== 2) {
257 symbols
[1] = VP8LReadBits(br
, 8);
259 code_lengths
[1] = num_symbols
- 1;
261 ok
= HuffmanTreeBuildExplicit(tree
, code_lengths
, codes
, symbols
,
262 alphabet_size
, num_symbols
);
263 } else { // Decode Huffman-coded code lengths.
264 int* code_lengths
= NULL
;
266 int code_length_code_lengths
[NUM_CODE_LENGTH_CODES
] = { 0 };
267 const int num_codes
= VP8LReadBits(br
, 4) + 4;
268 if (num_codes
> NUM_CODE_LENGTH_CODES
) {
269 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
274 (int*)WebPSafeCalloc((uint64_t)alphabet_size
, sizeof(*code_lengths
));
275 if (code_lengths
== NULL
) {
276 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
280 for (i
= 0; i
< num_codes
; ++i
) {
281 code_length_code_lengths
[kCodeLengthCodeOrder
[i
]] = VP8LReadBits(br
, 3);
283 ok
= ReadHuffmanCodeLengths(dec
, code_length_code_lengths
, alphabet_size
,
286 ok
= HuffmanTreeBuildImplicit(tree
, code_lengths
, alphabet_size
);
290 ok
= ok
&& !br
->error_
;
292 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
298 static void DeleteHtreeGroups(HTreeGroup
* htree_groups
, int num_htree_groups
) {
299 if (htree_groups
!= NULL
) {
301 for (i
= 0; i
< num_htree_groups
; ++i
) {
302 HuffmanTree
* const htrees
= htree_groups
[i
].htrees_
;
303 for (j
= 0; j
< HUFFMAN_CODES_PER_META_CODE
; ++j
) {
304 HuffmanTreeRelease(&htrees
[j
]);
311 static int ReadHuffmanCodes(VP8LDecoder
* const dec
, int xsize
, int ysize
,
312 int color_cache_bits
, int allow_recursion
) {
314 VP8LBitReader
* const br
= &dec
->br_
;
315 VP8LMetadata
* const hdr
= &dec
->hdr_
;
316 uint32_t* huffman_image
= NULL
;
317 HTreeGroup
* htree_groups
= NULL
;
318 int num_htree_groups
= 1;
320 if (allow_recursion
&& VP8LReadBits(br
, 1)) {
321 // use meta Huffman codes.
322 const int huffman_precision
= VP8LReadBits(br
, 3) + 2;
323 const int huffman_xsize
= VP8LSubSampleSize(xsize
, huffman_precision
);
324 const int huffman_ysize
= VP8LSubSampleSize(ysize
, huffman_precision
);
325 const int huffman_pixs
= huffman_xsize
* huffman_ysize
;
326 if (!DecodeImageStream(huffman_xsize
, huffman_ysize
, 0, dec
,
328 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
331 hdr
->huffman_subsample_bits_
= huffman_precision
;
332 for (i
= 0; i
< huffman_pixs
; ++i
) {
333 // The huffman data is stored in red and green bytes.
334 const int group
= (huffman_image
[i
] >> 8) & 0xffff;
335 huffman_image
[i
] = group
;
336 if (group
>= num_htree_groups
) {
337 num_htree_groups
= group
+ 1;
342 if (br
->error_
) goto Error
;
344 assert(num_htree_groups
<= 0x10000);
346 (HTreeGroup
*)WebPSafeCalloc((uint64_t)num_htree_groups
,
347 sizeof(*htree_groups
));
348 if (htree_groups
== NULL
) {
349 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
353 for (i
= 0; i
< num_htree_groups
; ++i
) {
354 HuffmanTree
* const htrees
= htree_groups
[i
].htrees_
;
355 for (j
= 0; j
< HUFFMAN_CODES_PER_META_CODE
; ++j
) {
356 int alphabet_size
= kAlphabetSize
[j
];
357 if (j
== 0 && color_cache_bits
> 0) {
358 alphabet_size
+= 1 << color_cache_bits
;
360 if (!ReadHuffmanCode(alphabet_size
, dec
, htrees
+ j
)) goto Error
;
364 // All OK. Finalize pointers and return.
365 hdr
->huffman_image_
= huffman_image
;
366 hdr
->num_htree_groups_
= num_htree_groups
;
367 hdr
->htree_groups_
= htree_groups
;
372 DeleteHtreeGroups(htree_groups
, num_htree_groups
);
376 //------------------------------------------------------------------------------
379 static int AllocateAndInitRescaler(VP8LDecoder
* const dec
, VP8Io
* const io
) {
380 const int num_channels
= 4;
381 const int in_width
= io
->mb_w
;
382 const int out_width
= io
->scaled_width
;
383 const int in_height
= io
->mb_h
;
384 const int out_height
= io
->scaled_height
;
385 const uint64_t work_size
= 2 * num_channels
* (uint64_t)out_width
;
386 int32_t* work
; // Rescaler work area.
387 const uint64_t scaled_data_size
= num_channels
* (uint64_t)out_width
;
388 uint32_t* scaled_data
; // Temporary storage for scaled BGRA data.
389 const uint64_t memory_size
= sizeof(*dec
->rescaler
) +
390 work_size
* sizeof(*work
) +
391 scaled_data_size
* sizeof(*scaled_data
);
392 uint8_t* memory
= (uint8_t*)WebPSafeCalloc(memory_size
, sizeof(*memory
));
393 if (memory
== NULL
) {
394 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
397 assert(dec
->rescaler_memory
== NULL
);
398 dec
->rescaler_memory
= memory
;
400 dec
->rescaler
= (WebPRescaler
*)memory
;
401 memory
+= sizeof(*dec
->rescaler
);
402 work
= (int32_t*)memory
;
403 memory
+= work_size
* sizeof(*work
);
404 scaled_data
= (uint32_t*)memory
;
406 WebPRescalerInit(dec
->rescaler
, in_width
, in_height
, (uint8_t*)scaled_data
,
407 out_width
, out_height
, 0, num_channels
,
408 in_width
, out_width
, in_height
, out_height
, work
);
412 //------------------------------------------------------------------------------
415 // We have special "export" function since we need to convert from BGRA
416 static int Export(WebPRescaler
* const rescaler
, WEBP_CSP_MODE colorspace
,
417 int rgba_stride
, uint8_t* const rgba
) {
418 uint32_t* const src
= (uint32_t*)rescaler
->dst
;
419 const int dst_width
= rescaler
->dst_width
;
420 int num_lines_out
= 0;
421 while (WebPRescalerHasPendingOutput(rescaler
)) {
422 uint8_t* const dst
= rgba
+ num_lines_out
* rgba_stride
;
423 WebPRescalerExportRow(rescaler
);
424 WebPMultARGBRow(src
, dst_width
, 1);
425 VP8LConvertFromBGRA(src
, dst_width
, colorspace
, dst
);
428 return num_lines_out
;
432 static int EmitRescaledRowsRGBA(const VP8LDecoder
* const dec
,
433 uint8_t* in
, int in_stride
, int mb_h
,
434 uint8_t* const out
, int out_stride
) {
435 const WEBP_CSP_MODE colorspace
= dec
->output_
->colorspace
;
436 int num_lines_in
= 0;
437 int num_lines_out
= 0;
438 while (num_lines_in
< mb_h
) {
439 uint8_t* const row_in
= in
+ num_lines_in
* in_stride
;
440 uint8_t* const row_out
= out
+ num_lines_out
* out_stride
;
441 const int lines_left
= mb_h
- num_lines_in
;
442 const int needed_lines
= WebPRescaleNeededLines(dec
->rescaler
, lines_left
);
443 assert(needed_lines
> 0 && needed_lines
<= lines_left
);
444 WebPMultARGBRows(row_in
, in_stride
,
445 dec
->rescaler
->src_width
, needed_lines
, 0);
446 WebPRescalerImport(dec
->rescaler
, lines_left
, row_in
, in_stride
);
447 num_lines_in
+= needed_lines
;
448 num_lines_out
+= Export(dec
->rescaler
, colorspace
, out_stride
, row_out
);
450 return num_lines_out
;
453 // Emit rows without any scaling.
454 static int EmitRows(WEBP_CSP_MODE colorspace
,
455 const uint8_t* row_in
, int in_stride
,
457 uint8_t* const out
, int out_stride
) {
459 uint8_t* row_out
= out
;
460 while (lines
-- > 0) {
461 VP8LConvertFromBGRA((const uint32_t*)row_in
, mb_w
, colorspace
, row_out
);
463 row_out
+= out_stride
;
465 return mb_h
; // Num rows out == num rows in.
468 //------------------------------------------------------------------------------
471 static void ConvertToYUVA(const uint32_t* const src
, int width
, int y_pos
,
472 const WebPDecBuffer
* const output
) {
473 const WebPYUVABuffer
* const buf
= &output
->u
.YUVA
;
474 // first, the luma plane
477 uint8_t* const y
= buf
->y
+ y_pos
* buf
->y_stride
;
478 for (i
= 0; i
< width
; ++i
) {
479 const uint32_t p
= src
[i
];
480 y
[i
] = VP8RGBToY((p
>> 16) & 0xff, (p
>> 8) & 0xff, (p
>> 0) & 0xff,
487 uint8_t* const u
= buf
->u
+ (y_pos
>> 1) * buf
->u_stride
;
488 uint8_t* const v
= buf
->v
+ (y_pos
>> 1) * buf
->v_stride
;
489 const int uv_width
= width
>> 1;
491 for (i
= 0; i
< uv_width
; ++i
) {
492 const uint32_t v0
= src
[2 * i
+ 0];
493 const uint32_t v1
= src
[2 * i
+ 1];
494 // VP8RGBToU/V expects four accumulated pixels. Hence we need to
495 // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
496 const int r
= ((v0
>> 15) & 0x1fe) + ((v1
>> 15) & 0x1fe);
497 const int g
= ((v0
>> 7) & 0x1fe) + ((v1
>> 7) & 0x1fe);
498 const int b
= ((v0
<< 1) & 0x1fe) + ((v1
<< 1) & 0x1fe);
499 if (!(y_pos
& 1)) { // even lines: store values
500 u
[i
] = VP8RGBToU(r
, g
, b
, YUV_HALF
<< 2);
501 v
[i
] = VP8RGBToV(r
, g
, b
, YUV_HALF
<< 2);
502 } else { // odd lines: average with previous values
503 const int tmp_u
= VP8RGBToU(r
, g
, b
, YUV_HALF
<< 2);
504 const int tmp_v
= VP8RGBToV(r
, g
, b
, YUV_HALF
<< 2);
505 // Approximated average-of-four. But it's an acceptable diff.
506 u
[i
] = (u
[i
] + tmp_u
+ 1) >> 1;
507 v
[i
] = (v
[i
] + tmp_v
+ 1) >> 1;
510 if (width
& 1) { // last pixel
511 const uint32_t v0
= src
[2 * i
+ 0];
512 const int r
= (v0
>> 14) & 0x3fc;
513 const int g
= (v0
>> 6) & 0x3fc;
514 const int b
= (v0
<< 2) & 0x3fc;
515 if (!(y_pos
& 1)) { // even lines
516 u
[i
] = VP8RGBToU(r
, g
, b
, YUV_HALF
<< 2);
517 v
[i
] = VP8RGBToV(r
, g
, b
, YUV_HALF
<< 2);
518 } else { // odd lines (note: we could just skip this)
519 const int tmp_u
= VP8RGBToU(r
, g
, b
, YUV_HALF
<< 2);
520 const int tmp_v
= VP8RGBToV(r
, g
, b
, YUV_HALF
<< 2);
521 u
[i
] = (u
[i
] + tmp_u
+ 1) >> 1;
522 v
[i
] = (v
[i
] + tmp_v
+ 1) >> 1;
526 // Lastly, store alpha if needed.
527 if (buf
->a
!= NULL
) {
529 uint8_t* const a
= buf
->a
+ y_pos
* buf
->a_stride
;
530 for (i
= 0; i
< width
; ++i
) a
[i
] = (src
[i
] >> 24);
534 static int ExportYUVA(const VP8LDecoder
* const dec
, int y_pos
) {
535 WebPRescaler
* const rescaler
= dec
->rescaler
;
536 uint32_t* const src
= (uint32_t*)rescaler
->dst
;
537 const int dst_width
= rescaler
->dst_width
;
538 int num_lines_out
= 0;
539 while (WebPRescalerHasPendingOutput(rescaler
)) {
540 WebPRescalerExportRow(rescaler
);
541 WebPMultARGBRow(src
, dst_width
, 1);
542 ConvertToYUVA(src
, dst_width
, y_pos
, dec
->output_
);
546 return num_lines_out
;
549 static int EmitRescaledRowsYUVA(const VP8LDecoder
* const dec
,
550 uint8_t* in
, int in_stride
, int mb_h
) {
551 int num_lines_in
= 0;
552 int y_pos
= dec
->last_out_row_
;
553 while (num_lines_in
< mb_h
) {
554 const int lines_left
= mb_h
- num_lines_in
;
555 const int needed_lines
= WebPRescaleNeededLines(dec
->rescaler
, lines_left
);
556 WebPMultARGBRows(in
, in_stride
, dec
->rescaler
->src_width
, needed_lines
, 0);
557 WebPRescalerImport(dec
->rescaler
, lines_left
, in
, in_stride
);
558 num_lines_in
+= needed_lines
;
559 in
+= needed_lines
* in_stride
;
560 y_pos
+= ExportYUVA(dec
, y_pos
);
565 static int EmitRowsYUVA(const VP8LDecoder
* const dec
,
566 const uint8_t* in
, int in_stride
,
567 int mb_w
, int num_rows
) {
568 int y_pos
= dec
->last_out_row_
;
569 while (num_rows
-- > 0) {
570 ConvertToYUVA((const uint32_t*)in
, mb_w
, y_pos
, dec
->output_
);
577 //------------------------------------------------------------------------------
580 // Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
581 // crop options. Also updates the input data pointer, so that it points to the
582 // start of the cropped window. Note that pixels are in ARGB format even if
583 // 'in_data' is uint8_t*.
584 // Returns true if the crop window is not empty.
585 static int SetCropWindow(VP8Io
* const io
, int y_start
, int y_end
,
586 uint8_t** const in_data
, int pixel_stride
) {
587 assert(y_start
< y_end
);
588 assert(io
->crop_left
< io
->crop_right
);
589 if (y_end
> io
->crop_bottom
) {
590 y_end
= io
->crop_bottom
; // make sure we don't overflow on last row.
592 if (y_start
< io
->crop_top
) {
593 const int delta
= io
->crop_top
- y_start
;
594 y_start
= io
->crop_top
;
595 *in_data
+= delta
* pixel_stride
;
597 if (y_start
>= y_end
) return 0; // Crop window is empty.
599 *in_data
+= io
->crop_left
* sizeof(uint32_t);
601 io
->mb_y
= y_start
- io
->crop_top
;
602 io
->mb_w
= io
->crop_right
- io
->crop_left
;
603 io
->mb_h
= y_end
- y_start
;
604 return 1; // Non-empty crop window.
607 //------------------------------------------------------------------------------
609 static WEBP_INLINE
int GetMetaIndex(
610 const uint32_t* const image
, int xsize
, int bits
, int x
, int y
) {
611 if (bits
== 0) return 0;
612 return image
[xsize
* (y
>> bits
) + (x
>> bits
)];
615 static WEBP_INLINE HTreeGroup
* GetHtreeGroupForPos(VP8LMetadata
* const hdr
,
617 const int meta_index
= GetMetaIndex(hdr
->huffman_image_
, hdr
->huffman_xsize_
,
618 hdr
->huffman_subsample_bits_
, x
, y
);
619 assert(meta_index
< hdr
->num_htree_groups_
);
620 return hdr
->htree_groups_
+ meta_index
;
623 //------------------------------------------------------------------------------
624 // Main loop, with custom row-processing function
626 typedef void (*ProcessRowsFunc
)(VP8LDecoder
* const dec
, int row
);
628 static void ApplyInverseTransforms(VP8LDecoder
* const dec
, int num_rows
,
629 const uint32_t* const rows
) {
630 int n
= dec
->next_transform_
;
631 const int cache_pixs
= dec
->width_
* num_rows
;
632 const int start_row
= dec
->last_row_
;
633 const int end_row
= start_row
+ num_rows
;
634 const uint32_t* rows_in
= rows
;
635 uint32_t* const rows_out
= dec
->argb_cache_
;
637 // Inverse transforms.
638 // TODO: most transforms only need to operate on the cropped region only.
639 memcpy(rows_out
, rows_in
, cache_pixs
* sizeof(*rows_out
));
641 VP8LTransform
* const transform
= &dec
->transforms_
[n
];
642 VP8LInverseTransform(transform
, start_row
, end_row
, rows_in
, rows_out
);
647 // Special method for paletted alpha data.
648 static void ApplyInverseTransformsAlpha(VP8LDecoder
* const dec
, int num_rows
,
649 const uint8_t* const rows
) {
650 const int start_row
= dec
->last_row_
;
651 const int end_row
= start_row
+ num_rows
;
652 const uint8_t* rows_in
= rows
;
653 uint8_t* rows_out
= (uint8_t*)dec
->io_
->opaque
+ dec
->io_
->width
* start_row
;
654 VP8LTransform
* const transform
= &dec
->transforms_
[0];
655 assert(dec
->next_transform_
== 1);
656 assert(transform
->type_
== COLOR_INDEXING_TRANSFORM
);
657 VP8LColorIndexInverseTransformAlpha(transform
, start_row
, end_row
, rows_in
,
661 // Processes (transforms, scales & color-converts) the rows decoded after the
663 static void ProcessRows(VP8LDecoder
* const dec
, int row
) {
664 const uint32_t* const rows
= dec
->pixels_
+ dec
->width_
* dec
->last_row_
;
665 const int num_rows
= row
- dec
->last_row_
;
667 if (num_rows
<= 0) return; // Nothing to be done.
668 ApplyInverseTransforms(dec
, num_rows
, rows
);
672 VP8Io
* const io
= dec
->io_
;
673 uint8_t* rows_data
= (uint8_t*)dec
->argb_cache_
;
674 const int in_stride
= io
->width
* sizeof(uint32_t); // in unit of RGBA
675 if (!SetCropWindow(io
, dec
->last_row_
, row
, &rows_data
, in_stride
)) {
676 // Nothing to output (this time).
678 const WebPDecBuffer
* const output
= dec
->output_
;
679 if (output
->colorspace
< MODE_YUV
) { // convert to RGBA
680 const WebPRGBABuffer
* const buf
= &output
->u
.RGBA
;
681 uint8_t* const rgba
= buf
->rgba
+ dec
->last_out_row_
* buf
->stride
;
682 const int num_rows_out
= io
->use_scaling
?
683 EmitRescaledRowsRGBA(dec
, rows_data
, in_stride
, io
->mb_h
,
685 EmitRows(output
->colorspace
, rows_data
, in_stride
,
686 io
->mb_w
, io
->mb_h
, rgba
, buf
->stride
);
687 // Update 'last_out_row_'.
688 dec
->last_out_row_
+= num_rows_out
;
689 } else { // convert to YUVA
690 dec
->last_out_row_
= io
->use_scaling
?
691 EmitRescaledRowsYUVA(dec
, rows_data
, in_stride
, io
->mb_h
) :
692 EmitRowsYUVA(dec
, rows_data
, in_stride
, io
->mb_w
, io
->mb_h
);
694 assert(dec
->last_out_row_
<= output
->height
);
698 // Update 'last_row_'.
699 dec
->last_row_
= row
;
700 assert(dec
->last_row_
<= dec
->height_
);
703 // Row-processing for the special case when alpha data contains only one
704 // transform (color indexing), and trivial non-green literals.
705 static int Is8bOptimizable(const VP8LMetadata
* const hdr
) {
707 if (hdr
->color_cache_size_
> 0) return 0;
708 // When the Huffman tree contains only one symbol, we can skip the
709 // call to ReadSymbol() for red/blue/alpha channels.
710 for (i
= 0; i
< hdr
->num_htree_groups_
; ++i
) {
711 const HuffmanTree
* const htrees
= hdr
->htree_groups_
[i
].htrees_
;
712 if (htrees
[RED
].num_nodes_
> 1) return 0;
713 if (htrees
[BLUE
].num_nodes_
> 1) return 0;
714 if (htrees
[ALPHA
].num_nodes_
> 1) return 0;
719 static void ExtractPalettedAlphaRows(VP8LDecoder
* const dec
, int row
) {
720 const int num_rows
= row
- dec
->last_row_
;
721 const uint8_t* const in
=
722 (uint8_t*)dec
->pixels_
+ dec
->width_
* dec
->last_row_
;
724 ApplyInverseTransformsAlpha(dec
, num_rows
, in
);
726 dec
->last_row_
= dec
->last_out_row_
= row
;
729 static int DecodeAlphaData(VP8LDecoder
* const dec
, uint8_t* const data
,
730 int width
, int height
, int last_row
) {
732 int row
= dec
->last_pixel_
/ width
;
733 int col
= dec
->last_pixel_
% width
;
734 VP8LBitReader
* const br
= &dec
->br_
;
735 VP8LMetadata
* const hdr
= &dec
->hdr_
;
736 const HTreeGroup
* htree_group
= GetHtreeGroupForPos(hdr
, col
, row
);
737 int pos
= dec
->last_pixel_
; // current position
738 const int end
= width
* height
; // End of data
739 const int last
= width
* last_row
; // Last pixel to decode
740 const int len_code_limit
= NUM_LITERAL_CODES
+ NUM_LENGTH_CODES
;
741 const int mask
= hdr
->huffman_mask_
;
742 assert(htree_group
!= NULL
);
744 assert(last_row
<= height
);
745 assert(Is8bOptimizable(hdr
));
747 while (!br
->eos_
&& pos
< last
) {
749 // Only update when changing tile.
750 if ((col
& mask
) == 0) {
751 htree_group
= GetHtreeGroupForPos(hdr
, col
, row
);
753 VP8LFillBitWindow(br
);
754 code
= ReadSymbol(&htree_group
->htrees_
[GREEN
], br
);
755 if (code
< NUM_LITERAL_CODES
) { // Literal
762 if (row
% NUM_ARGB_CACHE_ROWS
== 0) {
763 ExtractPalettedAlphaRows(dec
, row
);
766 } else if (code
< len_code_limit
) { // Backward reference
768 const int length_sym
= code
- NUM_LITERAL_CODES
;
769 const int length
= GetCopyLength(length_sym
, br
);
770 const int dist_symbol
= ReadSymbol(&htree_group
->htrees_
[DIST
], br
);
771 VP8LFillBitWindow(br
);
772 dist_code
= GetCopyDistance(dist_symbol
, br
);
773 dist
= PlaneCodeToDistance(width
, dist_code
);
774 if (pos
>= dist
&& end
- pos
>= length
) {
776 for (i
= 0; i
< length
; ++i
) data
[pos
+ i
] = data
[pos
+ i
- dist
];
783 while (col
>= width
) {
786 if (row
% NUM_ARGB_CACHE_ROWS
== 0) {
787 ExtractPalettedAlphaRows(dec
, row
);
790 if (pos
< last
&& (col
& mask
)) {
791 htree_group
= GetHtreeGroupForPos(hdr
, col
, row
);
793 } else { // Not reached
800 // Process the remaining rows corresponding to last row-block.
801 ExtractPalettedAlphaRows(dec
, row
);
804 if (br
->error_
|| !ok
|| (br
->eos_
&& pos
< end
)) {
806 dec
->status_
= br
->eos_
? VP8_STATUS_SUSPENDED
807 : VP8_STATUS_BITSTREAM_ERROR
;
809 dec
->last_pixel_
= (int)pos
;
810 if (pos
== end
) dec
->state_
= READ_DATA
;
815 static int DecodeImageData(VP8LDecoder
* const dec
, uint32_t* const data
,
816 int width
, int height
, int last_row
,
817 ProcessRowsFunc process_func
) {
819 int row
= dec
->last_pixel_
/ width
;
820 int col
= dec
->last_pixel_
% width
;
821 VP8LBitReader
* const br
= &dec
->br_
;
822 VP8LMetadata
* const hdr
= &dec
->hdr_
;
823 HTreeGroup
* htree_group
= GetHtreeGroupForPos(hdr
, col
, row
);
824 uint32_t* src
= data
+ dec
->last_pixel_
;
825 uint32_t* last_cached
= src
;
826 uint32_t* const src_end
= data
+ width
* height
; // End of data
827 uint32_t* const src_last
= data
+ width
* last_row
; // Last pixel to decode
828 const int len_code_limit
= NUM_LITERAL_CODES
+ NUM_LENGTH_CODES
;
829 const int color_cache_limit
= len_code_limit
+ hdr
->color_cache_size_
;
830 VP8LColorCache
* const color_cache
=
831 (hdr
->color_cache_size_
> 0) ? &hdr
->color_cache_
: NULL
;
832 const int mask
= hdr
->huffman_mask_
;
833 assert(htree_group
!= NULL
);
834 assert(src
< src_end
);
835 assert(src_last
<= src_end
);
837 while (!br
->eos_
&& src
< src_last
) {
839 // Only update when changing tile. Note we could use this test:
840 // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
841 // but that's actually slower and needs storing the previous col/row.
842 if ((col
& mask
) == 0) {
843 htree_group
= GetHtreeGroupForPos(hdr
, col
, row
);
845 VP8LFillBitWindow(br
);
846 code
= ReadSymbol(&htree_group
->htrees_
[GREEN
], br
);
847 if (code
< NUM_LITERAL_CODES
) { // Literal
848 int red
, green
, blue
, alpha
;
849 red
= ReadSymbol(&htree_group
->htrees_
[RED
], br
);
851 VP8LFillBitWindow(br
);
852 blue
= ReadSymbol(&htree_group
->htrees_
[BLUE
], br
);
853 alpha
= ReadSymbol(&htree_group
->htrees_
[ALPHA
], br
);
854 *src
= (alpha
<< 24) | (red
<< 16) | (green
<< 8) | blue
;
861 if ((row
% NUM_ARGB_CACHE_ROWS
== 0) && (process_func
!= NULL
)) {
862 process_func(dec
, row
);
864 if (color_cache
!= NULL
) {
865 while (last_cached
< src
) {
866 VP8LColorCacheInsert(color_cache
, *last_cached
++);
870 } else if (code
< len_code_limit
) { // Backward reference
872 const int length_sym
= code
- NUM_LITERAL_CODES
;
873 const int length
= GetCopyLength(length_sym
, br
);
874 const int dist_symbol
= ReadSymbol(&htree_group
->htrees_
[DIST
], br
);
875 VP8LFillBitWindow(br
);
876 dist_code
= GetCopyDistance(dist_symbol
, br
);
877 dist
= PlaneCodeToDistance(width
, dist_code
);
878 if (src
- data
< (ptrdiff_t)dist
|| src_end
- src
< (ptrdiff_t)length
) {
883 for (i
= 0; i
< length
; ++i
) src
[i
] = src
[i
- dist
];
887 while (col
>= width
) {
890 if ((row
% NUM_ARGB_CACHE_ROWS
== 0) && (process_func
!= NULL
)) {
891 process_func(dec
, row
);
894 if (src
< src_last
) {
895 if (col
& mask
) htree_group
= GetHtreeGroupForPos(hdr
, col
, row
);
896 if (color_cache
!= NULL
) {
897 while (last_cached
< src
) {
898 VP8LColorCacheInsert(color_cache
, *last_cached
++);
902 } else if (code
< color_cache_limit
) { // Color cache
903 const int key
= code
- len_code_limit
;
904 assert(color_cache
!= NULL
);
905 while (last_cached
< src
) {
906 VP8LColorCacheInsert(color_cache
, *last_cached
++);
908 *src
= VP8LColorCacheLookup(color_cache
, key
);
910 } else { // Not reached
917 // Process the remaining rows corresponding to last row-block.
918 if (process_func
!= NULL
) process_func(dec
, row
);
921 if (br
->error_
|| !ok
|| (br
->eos_
&& src
< src_end
)) {
923 dec
->status_
= br
->eos_
? VP8_STATUS_SUSPENDED
924 : VP8_STATUS_BITSTREAM_ERROR
;
926 dec
->last_pixel_
= (int)(src
- data
);
927 if (src
== src_end
) dec
->state_
= READ_DATA
;
932 // -----------------------------------------------------------------------------
935 static void ClearTransform(VP8LTransform
* const transform
) {
936 free(transform
->data_
);
937 transform
->data_
= NULL
;
940 // For security reason, we need to remap the color map to span
941 // the total possible bundled values, and not just the num_colors.
942 static int ExpandColorMap(int num_colors
, VP8LTransform
* const transform
) {
944 const int final_num_colors
= 1 << (8 >> transform
->bits_
);
945 uint32_t* const new_color_map
=
946 (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors
,
947 sizeof(*new_color_map
));
948 if (new_color_map
== NULL
) {
951 uint8_t* const data
= (uint8_t*)transform
->data_
;
952 uint8_t* const new_data
= (uint8_t*)new_color_map
;
953 new_color_map
[0] = transform
->data_
[0];
954 for (i
= 4; i
< 4 * num_colors
; ++i
) {
955 // Equivalent to AddPixelEq(), on a byte-basis.
956 new_data
[i
] = (data
[i
] + new_data
[i
- 4]) & 0xff;
958 for (; i
< 4 * final_num_colors
; ++i
)
959 new_data
[i
] = 0; // black tail.
960 free(transform
->data_
);
961 transform
->data_
= new_color_map
;
966 static int ReadTransform(int* const xsize
, int const* ysize
,
967 VP8LDecoder
* const dec
) {
969 VP8LBitReader
* const br
= &dec
->br_
;
970 VP8LTransform
* transform
= &dec
->transforms_
[dec
->next_transform_
];
971 const VP8LImageTransformType type
=
972 (VP8LImageTransformType
)VP8LReadBits(br
, 2);
974 // Each transform type can only be present once in the stream.
975 if (dec
->transforms_seen_
& (1U << type
)) {
976 return 0; // Already there, let's not accept the second same transform.
978 dec
->transforms_seen_
|= (1U << type
);
980 transform
->type_
= type
;
981 transform
->xsize_
= *xsize
;
982 transform
->ysize_
= *ysize
;
983 transform
->data_
= NULL
;
984 ++dec
->next_transform_
;
985 assert(dec
->next_transform_
<= NUM_TRANSFORMS
);
988 case PREDICTOR_TRANSFORM
:
989 case CROSS_COLOR_TRANSFORM
:
990 transform
->bits_
= VP8LReadBits(br
, 3) + 2;
991 ok
= DecodeImageStream(VP8LSubSampleSize(transform
->xsize_
,
993 VP8LSubSampleSize(transform
->ysize_
,
995 0, dec
, &transform
->data_
);
997 case COLOR_INDEXING_TRANSFORM
: {
998 const int num_colors
= VP8LReadBits(br
, 8) + 1;
999 const int bits
= (num_colors
> 16) ? 0
1000 : (num_colors
> 4) ? 1
1001 : (num_colors
> 2) ? 2
1003 *xsize
= VP8LSubSampleSize(transform
->xsize_
, bits
);
1004 transform
->bits_
= bits
;
1005 ok
= DecodeImageStream(num_colors
, 1, 0, dec
, &transform
->data_
);
1006 ok
= ok
&& ExpandColorMap(num_colors
, transform
);
1009 case SUBTRACT_GREEN
:
1012 assert(0); // can't happen
1019 // -----------------------------------------------------------------------------
1022 static void InitMetadata(VP8LMetadata
* const hdr
) {
1024 memset(hdr
, 0, sizeof(*hdr
));
1027 static void ClearMetadata(VP8LMetadata
* const hdr
) {
1030 free(hdr
->huffman_image_
);
1031 DeleteHtreeGroups(hdr
->htree_groups_
, hdr
->num_htree_groups_
);
1032 VP8LColorCacheClear(&hdr
->color_cache_
);
1036 // -----------------------------------------------------------------------------
1039 VP8LDecoder
* VP8LNew(void) {
1040 VP8LDecoder
* const dec
= (VP8LDecoder
*)calloc(1, sizeof(*dec
));
1041 if (dec
== NULL
) return NULL
;
1042 dec
->status_
= VP8_STATUS_OK
;
1043 dec
->action_
= READ_DIM
;
1044 dec
->state_
= READ_DIM
;
1046 VP8LDspInit(); // Init critical function pointers.
1051 void VP8LClear(VP8LDecoder
* const dec
) {
1053 if (dec
== NULL
) return;
1054 ClearMetadata(&dec
->hdr_
);
1057 dec
->pixels_
= NULL
;
1058 for (i
= 0; i
< dec
->next_transform_
; ++i
) {
1059 ClearTransform(&dec
->transforms_
[i
]);
1061 dec
->next_transform_
= 0;
1062 dec
->transforms_seen_
= 0;
1064 free(dec
->rescaler_memory
);
1065 dec
->rescaler_memory
= NULL
;
1067 dec
->output_
= NULL
; // leave no trace behind
1070 void VP8LDelete(VP8LDecoder
* const dec
) {
1077 static void UpdateDecoder(VP8LDecoder
* const dec
, int width
, int height
) {
1078 VP8LMetadata
* const hdr
= &dec
->hdr_
;
1079 const int num_bits
= hdr
->huffman_subsample_bits_
;
1080 dec
->width_
= width
;
1081 dec
->height_
= height
;
1083 hdr
->huffman_xsize_
= VP8LSubSampleSize(width
, num_bits
);
1084 hdr
->huffman_mask_
= (num_bits
== 0) ? ~0 : (1 << num_bits
) - 1;
1087 static int DecodeImageStream(int xsize
, int ysize
,
1089 VP8LDecoder
* const dec
,
1090 uint32_t** const decoded_data
) {
1092 int transform_xsize
= xsize
;
1093 int transform_ysize
= ysize
;
1094 VP8LBitReader
* const br
= &dec
->br_
;
1095 VP8LMetadata
* const hdr
= &dec
->hdr_
;
1096 uint32_t* data
= NULL
;
1097 int color_cache_bits
= 0;
1099 // Read the transforms (may recurse).
1101 while (ok
&& VP8LReadBits(br
, 1)) {
1102 ok
= ReadTransform(&transform_xsize
, &transform_ysize
, dec
);
1107 if (ok
&& VP8LReadBits(br
, 1)) {
1108 color_cache_bits
= VP8LReadBits(br
, 4);
1109 ok
= (color_cache_bits
>= 1 && color_cache_bits
<= MAX_CACHE_BITS
);
1111 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
1116 // Read the Huffman codes (may recurse).
1117 ok
= ok
&& ReadHuffmanCodes(dec
, transform_xsize
, transform_ysize
,
1118 color_cache_bits
, is_level0
);
1120 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
1124 // Finish setting up the color-cache
1125 if (color_cache_bits
> 0) {
1126 hdr
->color_cache_size_
= 1 << color_cache_bits
;
1127 if (!VP8LColorCacheInit(&hdr
->color_cache_
, color_cache_bits
)) {
1128 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
1133 hdr
->color_cache_size_
= 0;
1135 UpdateDecoder(dec
, transform_xsize
, transform_ysize
);
1137 if (is_level0
) { // level 0 complete
1138 dec
->state_
= READ_HDR
;
1143 const uint64_t total_size
= (uint64_t)transform_xsize
* transform_ysize
;
1144 data
= (uint32_t*)WebPSafeMalloc(total_size
, sizeof(*data
));
1146 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
1152 // Use the Huffman trees to decode the LZ77 encoded data.
1153 ok
= DecodeImageData(dec
, data
, transform_xsize
, transform_ysize
,
1154 transform_ysize
, NULL
);
1155 ok
= ok
&& !br
->error_
;
1162 // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
1163 // status appropriately.
1164 if (dec
->status_
== VP8_STATUS_BITSTREAM_ERROR
&& dec
->br_
.eos_
) {
1165 dec
->status_
= VP8_STATUS_SUSPENDED
;
1168 if (decoded_data
!= NULL
) {
1169 *decoded_data
= data
;
1171 // We allocate image data in this function only for transforms. At level 0
1172 // (that is: not the transforms), we shouldn't have allocated anything.
1173 assert(data
== NULL
);
1176 dec
->last_pixel_
= 0; // Reset for future DECODE_DATA_FUNC() calls.
1177 if (!is_level0
) ClearMetadata(hdr
); // Clean up temporary data behind.
1182 //------------------------------------------------------------------------------
1183 // Allocate internal buffers dec->pixels_ and dec->argb_cache_.
1184 static int AllocateInternalBuffers32b(VP8LDecoder
* const dec
, int final_width
) {
1185 const uint64_t num_pixels
= (uint64_t)dec
->width_
* dec
->height_
;
1186 // Scratch buffer corresponding to top-prediction row for transforming the
1187 // first row in the row-blocks. Not needed for paletted alpha.
1188 const uint64_t cache_top_pixels
= (uint16_t)final_width
;
1189 // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
1190 const uint64_t cache_pixels
= (uint64_t)final_width
* NUM_ARGB_CACHE_ROWS
;
1191 const uint64_t total_num_pixels
=
1192 num_pixels
+ cache_top_pixels
+ cache_pixels
;
1194 assert(dec
->width_
<= final_width
);
1195 dec
->pixels_
= (uint32_t*)WebPSafeMalloc(total_num_pixels
, sizeof(uint32_t));
1196 if (dec
->pixels_
== NULL
) {
1197 dec
->argb_cache_
= NULL
; // for sanity check
1198 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
1201 dec
->argb_cache_
= dec
->pixels_
+ num_pixels
+ cache_top_pixels
;
1205 static int AllocateInternalBuffers8b(VP8LDecoder
* const dec
) {
1206 const uint64_t total_num_pixels
= (uint64_t)dec
->width_
* dec
->height_
;
1207 dec
->argb_cache_
= NULL
; // for sanity check
1208 dec
->pixels_
= (uint32_t*)WebPSafeMalloc(total_num_pixels
, sizeof(uint8_t));
1209 if (dec
->pixels_
== NULL
) {
1210 dec
->status_
= VP8_STATUS_OUT_OF_MEMORY
;
1216 //------------------------------------------------------------------------------
1218 // Special row-processing that only stores the alpha data.
1219 static void ExtractAlphaRows(VP8LDecoder
* const dec
, int row
) {
1220 const int num_rows
= row
- dec
->last_row_
;
1221 const uint32_t* const in
= dec
->pixels_
+ dec
->width_
* dec
->last_row_
;
1223 if (num_rows
<= 0) return; // Nothing to be done.
1224 ApplyInverseTransforms(dec
, num_rows
, in
);
1226 // Extract alpha (which is stored in the green plane).
1228 const int width
= dec
->io_
->width
; // the final width (!= dec->width_)
1229 const int cache_pixs
= width
* num_rows
;
1230 uint8_t* const dst
= (uint8_t*)dec
->io_
->opaque
+ width
* dec
->last_row_
;
1231 const uint32_t* const src
= dec
->argb_cache_
;
1233 for (i
= 0; i
< cache_pixs
; ++i
) dst
[i
] = (src
[i
] >> 8) & 0xff;
1235 dec
->last_row_
= dec
->last_out_row_
= row
;
1238 int VP8LDecodeAlphaHeader(ALPHDecoder
* const alph_dec
,
1239 const uint8_t* const data
, size_t data_size
,
1240 uint8_t* const output
) {
1244 assert(alph_dec
!= NULL
);
1245 alph_dec
->vp8l_dec_
= VP8LNew();
1246 if (alph_dec
->vp8l_dec_
== NULL
) return 0;
1247 dec
= alph_dec
->vp8l_dec_
;
1249 dec
->width_
= alph_dec
->width_
;
1250 dec
->height_
= alph_dec
->height_
;
1251 dec
->io_
= &alph_dec
->io_
;
1255 WebPInitCustomIo(NULL
, io
); // Just a sanity Init. io won't be used.
1256 io
->opaque
= output
;
1257 io
->width
= alph_dec
->width_
;
1258 io
->height
= alph_dec
->height_
;
1260 dec
->status_
= VP8_STATUS_OK
;
1261 VP8LInitBitReader(&dec
->br_
, data
, data_size
);
1263 dec
->action_
= READ_HDR
;
1264 if (!DecodeImageStream(alph_dec
->width_
, alph_dec
->height_
, 1, dec
, NULL
)) {
1268 // Special case: if alpha data uses only the color indexing transform and
1269 // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
1270 // method that only needs allocation of 1 byte per pixel (alpha channel).
1271 if (dec
->next_transform_
== 1 &&
1272 dec
->transforms_
[0].type_
== COLOR_INDEXING_TRANSFORM
&&
1273 Is8bOptimizable(&dec
->hdr_
)) {
1274 alph_dec
->use_8b_decode
= 1;
1275 ok
= AllocateInternalBuffers8b(dec
);
1277 // Allocate internal buffers (note that dec->width_ may have changed here).
1278 alph_dec
->use_8b_decode
= 0;
1279 ok
= AllocateInternalBuffers32b(dec
, alph_dec
->width_
);
1284 dec
->action_
= READ_DATA
;
1288 VP8LDelete(alph_dec
->vp8l_dec_
);
1289 alph_dec
->vp8l_dec_
= NULL
;
1293 int VP8LDecodeAlphaImageStream(ALPHDecoder
* const alph_dec
, int last_row
) {
1294 VP8LDecoder
* const dec
= alph_dec
->vp8l_dec_
;
1295 assert(dec
!= NULL
);
1296 assert(dec
->action_
== READ_DATA
);
1297 assert(last_row
<= dec
->height_
);
1299 if (dec
->last_pixel_
== dec
->width_
* dec
->height_
) {
1303 // Decode (with special row processing).
1304 return alph_dec
->use_8b_decode
?
1305 DecodeAlphaData(dec
, (uint8_t*)dec
->pixels_
, dec
->width_
, dec
->height_
,
1307 DecodeImageData(dec
, dec
->pixels_
, dec
->width_
, dec
->height_
,
1308 last_row
, ExtractAlphaRows
);
1311 //------------------------------------------------------------------------------
1313 int VP8LDecodeHeader(VP8LDecoder
* const dec
, VP8Io
* const io
) {
1314 int width
, height
, has_alpha
;
1316 if (dec
== NULL
) return 0;
1318 dec
->status_
= VP8_STATUS_INVALID_PARAM
;
1323 dec
->status_
= VP8_STATUS_OK
;
1324 VP8LInitBitReader(&dec
->br_
, io
->data
, io
->data_size
);
1325 if (!ReadImageInfo(&dec
->br_
, &width
, &height
, &has_alpha
)) {
1326 dec
->status_
= VP8_STATUS_BITSTREAM_ERROR
;
1329 dec
->state_
= READ_DIM
;
1331 io
->height
= height
;
1333 dec
->action_
= READ_HDR
;
1334 if (!DecodeImageStream(width
, height
, 1, dec
, NULL
)) goto Error
;
1339 assert(dec
->status_
!= VP8_STATUS_OK
);
1343 int VP8LDecodeImage(VP8LDecoder
* const dec
) {
1345 WebPDecParams
* params
= NULL
;
1348 if (dec
== NULL
) return 0;
1352 params
= (WebPDecParams
*)io
->opaque
;
1353 assert(params
!= NULL
);
1354 dec
->output_
= params
->output
;
1355 assert(dec
->output_
!= NULL
);
1358 if (!WebPIoInitFromOptions(params
->options
, io
, MODE_BGRA
)) {
1359 dec
->status_
= VP8_STATUS_INVALID_PARAM
;
1363 if (!AllocateInternalBuffers32b(dec
, io
->width
)) goto Err
;
1365 if (io
->use_scaling
&& !AllocateAndInitRescaler(dec
, io
)) goto Err
;
1368 dec
->action_
= READ_DATA
;
1369 if (!DecodeImageData(dec
, dec
->pixels_
, dec
->width_
, dec
->height_
,
1370 dec
->height_
, ProcessRows
)) {
1375 params
->last_y
= dec
->last_out_row_
;
1381 assert(dec
->status_
!= VP8_STATUS_OK
);
1385 //------------------------------------------------------------------------------