Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libwebp/src/dec/vp8l_dec.c
9913 views
1
// Copyright 2012 Google Inc. All Rights Reserved.
2
//
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
// -----------------------------------------------------------------------------
9
//
10
// main entry for the decoder
11
//
12
// Authors: Vikas Arora ([email protected])
13
// Jyrki Alakuijala ([email protected])
14
15
#include <assert.h>
16
#include <stdlib.h>
17
18
#include "src/dec/alphai_dec.h"
19
#include "src/dec/vp8li_dec.h"
20
#include "src/dsp/dsp.h"
21
#include "src/dsp/lossless.h"
22
#include "src/dsp/lossless_common.h"
23
#include "src/utils/huffman_utils.h"
24
#include "src/utils/utils.h"
25
#include "src/webp/format_constants.h"
26
27
#define NUM_ARGB_CACHE_ROWS 16
28
29
static const int kCodeLengthLiterals = 16;
30
static const int kCodeLengthRepeatCode = 16;
31
static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 };
32
static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
33
34
// -----------------------------------------------------------------------------
35
// Five Huffman codes are used at each meta code:
36
// 1. green + length prefix codes + color cache codes,
37
// 2. alpha,
38
// 3. red,
39
// 4. blue, and,
40
// 5. distance prefix codes.
41
typedef enum {
42
GREEN = 0,
43
RED = 1,
44
BLUE = 2,
45
ALPHA = 3,
46
DIST = 4
47
} HuffIndex;
48
49
static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
50
NUM_LITERAL_CODES + NUM_LENGTH_CODES,
51
NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
52
NUM_DISTANCE_CODES
53
};
54
55
static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {
56
0, 1, 1, 1, 0
57
};
58
59
#define NUM_CODE_LENGTH_CODES 19
60
static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
61
17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
62
};
63
64
#define CODE_TO_PLANE_CODES 120
65
static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
66
0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
67
0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
68
0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
69
0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
70
0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
71
0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
72
0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
73
0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
74
0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
75
0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
76
0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
77
0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
78
};
79
80
// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha
81
// and distance alphabets are constant (256 for red, blue and alpha, 40 for
82
// distance) and lookup table sizes for them in worst case are 630 and 410
83
// respectively. Size of green alphabet depends on color cache size and is equal
84
// to 256 (green component values) + 24 (length prefix values)
85
// + color_cache_size (between 0 and 2048).
86
// All values computed for 8-bit first level lookup with Mark Adler's tool:
87
// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c
88
#define FIXED_TABLE_SIZE (630 * 3 + 410)
89
static const uint16_t kTableSize[12] = {
90
FIXED_TABLE_SIZE + 654,
91
FIXED_TABLE_SIZE + 656,
92
FIXED_TABLE_SIZE + 658,
93
FIXED_TABLE_SIZE + 662,
94
FIXED_TABLE_SIZE + 670,
95
FIXED_TABLE_SIZE + 686,
96
FIXED_TABLE_SIZE + 718,
97
FIXED_TABLE_SIZE + 782,
98
FIXED_TABLE_SIZE + 912,
99
FIXED_TABLE_SIZE + 1168,
100
FIXED_TABLE_SIZE + 1680,
101
FIXED_TABLE_SIZE + 2704
102
};
103
104
static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
105
// The oldest error reported takes precedence over the new one.
106
if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) {
107
dec->status_ = error;
108
}
109
return 0;
110
}
111
112
static int DecodeImageStream(int xsize, int ysize,
113
int is_level0,
114
VP8LDecoder* const dec,
115
uint32_t** const decoded_data);
116
117
//------------------------------------------------------------------------------
118
119
int VP8LCheckSignature(const uint8_t* const data, size_t size) {
120
return (size >= VP8L_FRAME_HEADER_SIZE &&
121
data[0] == VP8L_MAGIC_BYTE &&
122
(data[4] >> 5) == 0); // version
123
}
124
125
static int ReadImageInfo(VP8LBitReader* const br,
126
int* const width, int* const height,
127
int* const has_alpha) {
128
if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
129
*width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
130
*height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
131
*has_alpha = VP8LReadBits(br, 1);
132
if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;
133
return !br->eos_;
134
}
135
136
int VP8LGetInfo(const uint8_t* data, size_t data_size,
137
int* const width, int* const height, int* const has_alpha) {
138
if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
139
return 0; // not enough data
140
} else if (!VP8LCheckSignature(data, data_size)) {
141
return 0; // bad signature
142
} else {
143
int w, h, a;
144
VP8LBitReader br;
145
VP8LInitBitReader(&br, data, data_size);
146
if (!ReadImageInfo(&br, &w, &h, &a)) {
147
return 0;
148
}
149
if (width != NULL) *width = w;
150
if (height != NULL) *height = h;
151
if (has_alpha != NULL) *has_alpha = a;
152
return 1;
153
}
154
}
155
156
//------------------------------------------------------------------------------
157
158
static WEBP_INLINE int GetCopyDistance(int distance_symbol,
159
VP8LBitReader* const br) {
160
int extra_bits, offset;
161
if (distance_symbol < 4) {
162
return distance_symbol + 1;
163
}
164
extra_bits = (distance_symbol - 2) >> 1;
165
offset = (2 + (distance_symbol & 1)) << extra_bits;
166
return offset + VP8LReadBits(br, extra_bits) + 1;
167
}
168
169
static WEBP_INLINE int GetCopyLength(int length_symbol,
170
VP8LBitReader* const br) {
171
// Length and distance prefixes are encoded the same way.
172
return GetCopyDistance(length_symbol, br);
173
}
174
175
static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
176
if (plane_code > CODE_TO_PLANE_CODES) {
177
return plane_code - CODE_TO_PLANE_CODES;
178
} else {
179
const int dist_code = kCodeToPlane[plane_code - 1];
180
const int yoffset = dist_code >> 4;
181
const int xoffset = 8 - (dist_code & 0xf);
182
const int dist = yoffset * xsize + xoffset;
183
return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small
184
}
185
}
186
187
//------------------------------------------------------------------------------
188
// Decodes the next Huffman code from bit-stream.
189
// VP8LFillBitWindow(br) needs to be called at minimum every second call
190
// to ReadSymbol, in order to pre-fetch enough bits.
191
static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,
192
VP8LBitReader* const br) {
193
int nbits;
194
uint32_t val = VP8LPrefetchBits(br);
195
table += val & HUFFMAN_TABLE_MASK;
196
nbits = table->bits - HUFFMAN_TABLE_BITS;
197
if (nbits > 0) {
198
VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS);
199
val = VP8LPrefetchBits(br);
200
table += table->value;
201
table += val & ((1 << nbits) - 1);
202
}
203
VP8LSetBitPos(br, br->bit_pos_ + table->bits);
204
return table->value;
205
}
206
207
// Reads packed symbol depending on GREEN channel
208
#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask)
209
#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES
210
static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,
211
VP8LBitReader* const br,
212
uint32_t* const dst) {
213
const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);
214
const HuffmanCode32 code = group->packed_table[val];
215
assert(group->use_packed_table);
216
if (code.bits < BITS_SPECIAL_MARKER) {
217
VP8LSetBitPos(br, br->bit_pos_ + code.bits);
218
*dst = code.value;
219
return PACKED_NON_LITERAL_CODE;
220
} else {
221
VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER);
222
assert(code.value >= NUM_LITERAL_CODES);
223
return code.value;
224
}
225
}
226
227
static int AccumulateHCode(HuffmanCode hcode, int shift,
228
HuffmanCode32* const huff) {
229
huff->bits += hcode.bits;
230
huff->value |= (uint32_t)hcode.value << shift;
231
assert(huff->bits <= HUFFMAN_TABLE_BITS);
232
return hcode.bits;
233
}
234
235
static void BuildPackedTable(HTreeGroup* const htree_group) {
236
uint32_t code;
237
for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {
238
uint32_t bits = code;
239
HuffmanCode32* const huff = &htree_group->packed_table[bits];
240
HuffmanCode hcode = htree_group->htrees[GREEN][bits];
241
if (hcode.value >= NUM_LITERAL_CODES) {
242
huff->bits = hcode.bits + BITS_SPECIAL_MARKER;
243
huff->value = hcode.value;
244
} else {
245
huff->bits = 0;
246
huff->value = 0;
247
bits >>= AccumulateHCode(hcode, 8, huff);
248
bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);
249
bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);
250
bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);
251
(void)bits;
252
}
253
}
254
}
255
256
static int ReadHuffmanCodeLengths(
257
VP8LDecoder* const dec, const int* const code_length_code_lengths,
258
int num_symbols, int* const code_lengths) {
259
int ok = 0;
260
VP8LBitReader* const br = &dec->br_;
261
int symbol;
262
int max_symbol;
263
int prev_code_len = DEFAULT_CODE_LENGTH;
264
HuffmanTables tables;
265
266
if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
267
!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
268
code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
269
goto End;
270
}
271
272
if (VP8LReadBits(br, 1)) { // use length
273
const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
274
max_symbol = 2 + VP8LReadBits(br, length_nbits);
275
if (max_symbol > num_symbols) {
276
goto End;
277
}
278
} else {
279
max_symbol = num_symbols;
280
}
281
282
symbol = 0;
283
while (symbol < num_symbols) {
284
const HuffmanCode* p;
285
int code_len;
286
if (max_symbol-- == 0) break;
287
VP8LFillBitWindow(br);
288
p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
289
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
290
code_len = p->value;
291
if (code_len < kCodeLengthLiterals) {
292
code_lengths[symbol++] = code_len;
293
if (code_len != 0) prev_code_len = code_len;
294
} else {
295
const int use_prev = (code_len == kCodeLengthRepeatCode);
296
const int slot = code_len - kCodeLengthLiterals;
297
const int extra_bits = kCodeLengthExtraBits[slot];
298
const int repeat_offset = kCodeLengthRepeatOffsets[slot];
299
int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
300
if (symbol + repeat > num_symbols) {
301
goto End;
302
} else {
303
const int length = use_prev ? prev_code_len : 0;
304
while (repeat-- > 0) code_lengths[symbol++] = length;
305
}
306
}
307
}
308
ok = 1;
309
310
End:
311
VP8LHuffmanTablesDeallocate(&tables);
312
if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
313
return ok;
314
}
315
316
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
317
// tree.
318
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
319
int* const code_lengths,
320
HuffmanTables* const table) {
321
int ok = 0;
322
int size = 0;
323
VP8LBitReader* const br = &dec->br_;
324
const int simple_code = VP8LReadBits(br, 1);
325
326
memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
327
328
if (simple_code) { // Read symbols, codes & code lengths directly.
329
const int num_symbols = VP8LReadBits(br, 1) + 1;
330
const int first_symbol_len_code = VP8LReadBits(br, 1);
331
// The first code is either 1 bit or 8 bit code.
332
int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
333
code_lengths[symbol] = 1;
334
// The second code (if present), is always 8 bits long.
335
if (num_symbols == 2) {
336
symbol = VP8LReadBits(br, 8);
337
code_lengths[symbol] = 1;
338
}
339
ok = 1;
340
} else { // Decode Huffman-coded code lengths.
341
int i;
342
int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
343
const int num_codes = VP8LReadBits(br, 4) + 4;
344
assert(num_codes <= NUM_CODE_LENGTH_CODES);
345
346
for (i = 0; i < num_codes; ++i) {
347
code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
348
}
349
ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
350
code_lengths);
351
}
352
353
ok = ok && !br->eos_;
354
if (ok) {
355
size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
356
code_lengths, alphabet_size);
357
}
358
if (!ok || size == 0) {
359
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
360
}
361
return size;
362
}
363
364
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
365
int color_cache_bits, int allow_recursion) {
366
int i;
367
VP8LBitReader* const br = &dec->br_;
368
VP8LMetadata* const hdr = &dec->hdr_;
369
uint32_t* huffman_image = NULL;
370
HTreeGroup* htree_groups = NULL;
371
HuffmanTables* huffman_tables = &hdr->huffman_tables_;
372
int num_htree_groups = 1;
373
int num_htree_groups_max = 1;
374
int* mapping = NULL;
375
int ok = 0;
376
377
// Check the table has been 0 initialized (through InitMetadata).
378
assert(huffman_tables->root.start == NULL);
379
assert(huffman_tables->curr_segment == NULL);
380
381
if (allow_recursion && VP8LReadBits(br, 1)) {
382
// use meta Huffman codes.
383
const int huffman_precision =
384
MIN_HUFFMAN_BITS + VP8LReadBits(br, NUM_HUFFMAN_BITS);
385
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
386
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
387
const int huffman_pixs = huffman_xsize * huffman_ysize;
388
if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec,
389
&huffman_image)) {
390
goto Error;
391
}
392
hdr->huffman_subsample_bits_ = huffman_precision;
393
for (i = 0; i < huffman_pixs; ++i) {
394
// The huffman data is stored in red and green bytes.
395
const int group = (huffman_image[i] >> 8) & 0xffff;
396
huffman_image[i] = group;
397
if (group >= num_htree_groups_max) {
398
num_htree_groups_max = group + 1;
399
}
400
}
401
// Check the validity of num_htree_groups_max. If it seems too big, use a
402
// smaller value for later. This will prevent big memory allocations to end
403
// up with a bad bitstream anyway.
404
// The value of 1000 is totally arbitrary. We know that num_htree_groups_max
405
// is smaller than (1 << 16) and should be smaller than the number of pixels
406
// (though the format allows it to be bigger).
407
if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
408
// Create a mapping from the used indices to the minimal set of used
409
// values [0, num_htree_groups)
410
mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
411
if (mapping == NULL) {
412
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
413
goto Error;
414
}
415
// -1 means a value is unmapped, and therefore unused in the Huffman
416
// image.
417
memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));
418
for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
419
// Get the current mapping for the group and remap the Huffman image.
420
int* const mapped_group = &mapping[huffman_image[i]];
421
if (*mapped_group == -1) *mapped_group = num_htree_groups++;
422
huffman_image[i] = *mapped_group;
423
}
424
} else {
425
num_htree_groups = num_htree_groups_max;
426
}
427
}
428
429
if (br->eos_) goto Error;
430
431
if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,
432
num_htree_groups_max, mapping, dec,
433
huffman_tables, &htree_groups)) {
434
goto Error;
435
}
436
ok = 1;
437
438
// All OK. Finalize pointers.
439
hdr->huffman_image_ = huffman_image;
440
hdr->num_htree_groups_ = num_htree_groups;
441
hdr->htree_groups_ = htree_groups;
442
443
Error:
444
WebPSafeFree(mapping);
445
if (!ok) {
446
WebPSafeFree(huffman_image);
447
VP8LHuffmanTablesDeallocate(huffman_tables);
448
VP8LHtreeGroupsFree(htree_groups);
449
}
450
return ok;
451
}
452
453
int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,
454
int num_htree_groups_max, const int* const mapping,
455
VP8LDecoder* const dec,
456
HuffmanTables* const huffman_tables,
457
HTreeGroup** const htree_groups) {
458
int i, j, ok = 0;
459
const int max_alphabet_size =
460
kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0);
461
const int table_size = kTableSize[color_cache_bits];
462
int* code_lengths = NULL;
463
464
if ((mapping == NULL && num_htree_groups != num_htree_groups_max) ||
465
num_htree_groups > num_htree_groups_max) {
466
goto Error;
467
}
468
469
code_lengths =
470
(int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
471
*htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
472
473
if (*htree_groups == NULL || code_lengths == NULL ||
474
!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
475
huffman_tables)) {
476
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
477
goto Error;
478
}
479
480
for (i = 0; i < num_htree_groups_max; ++i) {
481
// If the index "i" is unused in the Huffman image, just make sure the
482
// coefficients are valid but do not store them.
483
if (mapping != NULL && mapping[i] == -1) {
484
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
485
int alphabet_size = kAlphabetSize[j];
486
if (j == 0 && color_cache_bits > 0) {
487
alphabet_size += (1 << color_cache_bits);
488
}
489
// Passing in NULL so that nothing gets filled.
490
if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {
491
goto Error;
492
}
493
}
494
} else {
495
HTreeGroup* const htree_group =
496
&(*htree_groups)[(mapping == NULL) ? i : mapping[i]];
497
HuffmanCode** const htrees = htree_group->htrees;
498
int size;
499
int total_size = 0;
500
int is_trivial_literal = 1;
501
int max_bits = 0;
502
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
503
int alphabet_size = kAlphabetSize[j];
504
if (j == 0 && color_cache_bits > 0) {
505
alphabet_size += (1 << color_cache_bits);
506
}
507
size =
508
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
509
htrees[j] = huffman_tables->curr_segment->curr_table;
510
if (size == 0) {
511
goto Error;
512
}
513
if (is_trivial_literal && kLiteralMap[j] == 1) {
514
is_trivial_literal = (htrees[j]->bits == 0);
515
}
516
total_size += htrees[j]->bits;
517
huffman_tables->curr_segment->curr_table += size;
518
if (j <= ALPHA) {
519
int local_max_bits = code_lengths[0];
520
int k;
521
for (k = 1; k < alphabet_size; ++k) {
522
if (code_lengths[k] > local_max_bits) {
523
local_max_bits = code_lengths[k];
524
}
525
}
526
max_bits += local_max_bits;
527
}
528
}
529
htree_group->is_trivial_literal = is_trivial_literal;
530
htree_group->is_trivial_code = 0;
531
if (is_trivial_literal) {
532
const int red = htrees[RED][0].value;
533
const int blue = htrees[BLUE][0].value;
534
const int alpha = htrees[ALPHA][0].value;
535
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
536
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
537
htree_group->is_trivial_code = 1;
538
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
539
}
540
}
541
htree_group->use_packed_table =
542
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
543
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
544
}
545
}
546
ok = 1;
547
548
Error:
549
WebPSafeFree(code_lengths);
550
if (!ok) {
551
VP8LHuffmanTablesDeallocate(huffman_tables);
552
VP8LHtreeGroupsFree(*htree_groups);
553
*htree_groups = NULL;
554
}
555
return ok;
556
}
557
558
//------------------------------------------------------------------------------
559
// Scaling.
560
561
#if !defined(WEBP_REDUCE_SIZE)
562
static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
563
const int num_channels = 4;
564
const int in_width = io->mb_w;
565
const int out_width = io->scaled_width;
566
const int in_height = io->mb_h;
567
const int out_height = io->scaled_height;
568
const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
569
rescaler_t* work; // Rescaler work area.
570
const uint64_t scaled_data_size = (uint64_t)out_width;
571
uint32_t* scaled_data; // Temporary storage for scaled BGRA data.
572
const uint64_t memory_size = sizeof(*dec->rescaler) +
573
work_size * sizeof(*work) +
574
scaled_data_size * sizeof(*scaled_data);
575
uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));
576
if (memory == NULL) {
577
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
578
}
579
assert(dec->rescaler_memory == NULL);
580
dec->rescaler_memory = memory;
581
582
dec->rescaler = (WebPRescaler*)memory;
583
memory += sizeof(*dec->rescaler);
584
work = (rescaler_t*)memory;
585
memory += work_size * sizeof(*work);
586
scaled_data = (uint32_t*)memory;
587
588
if (!WebPRescalerInit(dec->rescaler, in_width, in_height,
589
(uint8_t*)scaled_data, out_width, out_height,
590
0, num_channels, work)) {
591
return 0;
592
}
593
return 1;
594
}
595
#endif // WEBP_REDUCE_SIZE
596
597
//------------------------------------------------------------------------------
598
// Export to ARGB
599
600
#if !defined(WEBP_REDUCE_SIZE)
601
602
// We have special "export" function since we need to convert from BGRA
603
static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
604
int rgba_stride, uint8_t* const rgba) {
605
uint32_t* const src = (uint32_t*)rescaler->dst;
606
uint8_t* dst = rgba;
607
const int dst_width = rescaler->dst_width;
608
int num_lines_out = 0;
609
while (WebPRescalerHasPendingOutput(rescaler)) {
610
WebPRescalerExportRow(rescaler);
611
WebPMultARGBRow(src, dst_width, 1);
612
VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
613
dst += rgba_stride;
614
++num_lines_out;
615
}
616
return num_lines_out;
617
}
618
619
// Emit scaled rows.
620
static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
621
uint8_t* in, int in_stride, int mb_h,
622
uint8_t* const out, int out_stride) {
623
const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
624
int num_lines_in = 0;
625
int num_lines_out = 0;
626
while (num_lines_in < mb_h) {
627
uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride;
628
uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride;
629
const int lines_left = mb_h - num_lines_in;
630
const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
631
int lines_imported;
632
assert(needed_lines > 0 && needed_lines <= lines_left);
633
WebPMultARGBRows(row_in, in_stride,
634
dec->rescaler->src_width, needed_lines, 0);
635
lines_imported =
636
WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
637
assert(lines_imported == needed_lines);
638
num_lines_in += lines_imported;
639
num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
640
}
641
return num_lines_out;
642
}
643
644
#endif // WEBP_REDUCE_SIZE
645
646
// Emit rows without any scaling.
647
static int EmitRows(WEBP_CSP_MODE colorspace,
648
const uint8_t* row_in, int in_stride,
649
int mb_w, int mb_h,
650
uint8_t* const out, int out_stride) {
651
int lines = mb_h;
652
uint8_t* row_out = out;
653
while (lines-- > 0) {
654
VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
655
row_in += in_stride;
656
row_out += out_stride;
657
}
658
return mb_h; // Num rows out == num rows in.
659
}
660
661
//------------------------------------------------------------------------------
662
// Export to YUVA
663
664
static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
665
const WebPDecBuffer* const output) {
666
const WebPYUVABuffer* const buf = &output->u.YUVA;
667
668
// first, the luma plane
669
WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);
670
671
// then U/V planes
672
{
673
uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
674
uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
675
// even lines: store values
676
// odd lines: average with previous values
677
WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));
678
}
679
// Lastly, store alpha if needed.
680
if (buf->a != NULL) {
681
uint8_t* const a = buf->a + y_pos * buf->a_stride;
682
#if defined(WORDS_BIGENDIAN)
683
WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);
684
#else
685
WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);
686
#endif
687
}
688
}
689
690
static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
691
WebPRescaler* const rescaler = dec->rescaler;
692
uint32_t* const src = (uint32_t*)rescaler->dst;
693
const int dst_width = rescaler->dst_width;
694
int num_lines_out = 0;
695
while (WebPRescalerHasPendingOutput(rescaler)) {
696
WebPRescalerExportRow(rescaler);
697
WebPMultARGBRow(src, dst_width, 1);
698
ConvertToYUVA(src, dst_width, y_pos, dec->output_);
699
++y_pos;
700
++num_lines_out;
701
}
702
return num_lines_out;
703
}
704
705
static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
706
uint8_t* in, int in_stride, int mb_h) {
707
int num_lines_in = 0;
708
int y_pos = dec->last_out_row_;
709
while (num_lines_in < mb_h) {
710
const int lines_left = mb_h - num_lines_in;
711
const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
712
int lines_imported;
713
WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
714
lines_imported =
715
WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
716
assert(lines_imported == needed_lines);
717
num_lines_in += lines_imported;
718
in += needed_lines * in_stride;
719
y_pos += ExportYUVA(dec, y_pos);
720
}
721
return y_pos;
722
}
723
724
static int EmitRowsYUVA(const VP8LDecoder* const dec,
725
const uint8_t* in, int in_stride,
726
int mb_w, int num_rows) {
727
int y_pos = dec->last_out_row_;
728
while (num_rows-- > 0) {
729
ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
730
in += in_stride;
731
++y_pos;
732
}
733
return y_pos;
734
}
735
736
//------------------------------------------------------------------------------
737
// Cropping.
738
739
// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
740
// crop options. Also updates the input data pointer, so that it points to the
741
// start of the cropped window. Note that pixels are in ARGB format even if
742
// 'in_data' is uint8_t*.
743
// Returns true if the crop window is not empty.
744
static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
745
uint8_t** const in_data, int pixel_stride) {
746
assert(y_start < y_end);
747
assert(io->crop_left < io->crop_right);
748
if (y_end > io->crop_bottom) {
749
y_end = io->crop_bottom; // make sure we don't overflow on last row.
750
}
751
if (y_start < io->crop_top) {
752
const int delta = io->crop_top - y_start;
753
y_start = io->crop_top;
754
*in_data += delta * pixel_stride;
755
}
756
if (y_start >= y_end) return 0; // Crop window is empty.
757
758
*in_data += io->crop_left * sizeof(uint32_t);
759
760
io->mb_y = y_start - io->crop_top;
761
io->mb_w = io->crop_right - io->crop_left;
762
io->mb_h = y_end - y_start;
763
return 1; // Non-empty crop window.
764
}
765
766
//------------------------------------------------------------------------------
767
768
static WEBP_INLINE int GetMetaIndex(
769
const uint32_t* const image, int xsize, int bits, int x, int y) {
770
if (bits == 0) return 0;
771
return image[xsize * (y >> bits) + (x >> bits)];
772
}
773
774
static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
775
int x, int y) {
776
const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
777
hdr->huffman_subsample_bits_, x, y);
778
assert(meta_index < hdr->num_htree_groups_);
779
return hdr->htree_groups_ + meta_index;
780
}
781
782
//------------------------------------------------------------------------------
783
// Main loop, with custom row-processing function
784
785
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
786
787
static void ApplyInverseTransforms(VP8LDecoder* const dec,
788
int start_row, int num_rows,
789
const uint32_t* const rows) {
790
int n = dec->next_transform_;
791
const int cache_pixs = dec->width_ * num_rows;
792
const int end_row = start_row + num_rows;
793
const uint32_t* rows_in = rows;
794
uint32_t* const rows_out = dec->argb_cache_;
795
796
// Inverse transforms.
797
while (n-- > 0) {
798
VP8LTransform* const transform = &dec->transforms_[n];
799
VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
800
rows_in = rows_out;
801
}
802
if (rows_in != rows_out) {
803
// No transform called, hence just copy.
804
memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
805
}
806
}
807
808
// Processes (transforms, scales & color-converts) the rows decoded after the
809
// last call.
810
static void ProcessRows(VP8LDecoder* const dec, int row) {
811
const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
812
const int num_rows = row - dec->last_row_;
813
814
assert(row <= dec->io_->crop_bottom);
815
// We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size
816
// of argb_cache_), but we currently don't need more than that.
817
assert(num_rows <= NUM_ARGB_CACHE_ROWS);
818
if (num_rows > 0) { // Emit output.
819
VP8Io* const io = dec->io_;
820
uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
821
const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
822
ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
823
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
824
// Nothing to output (this time).
825
} else {
826
const WebPDecBuffer* const output = dec->output_;
827
if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA
828
const WebPRGBABuffer* const buf = &output->u.RGBA;
829
uint8_t* const rgba =
830
buf->rgba + (int64_t)dec->last_out_row_ * buf->stride;
831
const int num_rows_out =
832
#if !defined(WEBP_REDUCE_SIZE)
833
io->use_scaling ?
834
EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
835
rgba, buf->stride) :
836
#endif // WEBP_REDUCE_SIZE
837
EmitRows(output->colorspace, rows_data, in_stride,
838
io->mb_w, io->mb_h, rgba, buf->stride);
839
// Update 'last_out_row_'.
840
dec->last_out_row_ += num_rows_out;
841
} else { // convert to YUVA
842
dec->last_out_row_ = io->use_scaling ?
843
EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
844
EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
845
}
846
assert(dec->last_out_row_ <= output->height);
847
}
848
}
849
850
// Update 'last_row_'.
851
dec->last_row_ = row;
852
assert(dec->last_row_ <= dec->height_);
853
}
854
855
// Row-processing for the special case when alpha data contains only one
856
// transform (color indexing), and trivial non-green literals.
857
static int Is8bOptimizable(const VP8LMetadata* const hdr) {
858
int i;
859
if (hdr->color_cache_size_ > 0) return 0;
860
// When the Huffman tree contains only one symbol, we can skip the
861
// call to ReadSymbol() for red/blue/alpha channels.
862
for (i = 0; i < hdr->num_htree_groups_; ++i) {
863
HuffmanCode** const htrees = hdr->htree_groups_[i].htrees;
864
if (htrees[RED][0].bits > 0) return 0;
865
if (htrees[BLUE][0].bits > 0) return 0;
866
if (htrees[ALPHA][0].bits > 0) return 0;
867
}
868
return 1;
869
}
870
871
static void AlphaApplyFilter(ALPHDecoder* const alph_dec,
872
int first_row, int last_row,
873
uint8_t* out, int stride) {
874
if (alph_dec->filter_ != WEBP_FILTER_NONE) {
875
int y;
876
const uint8_t* prev_line = alph_dec->prev_line_;
877
assert(WebPUnfilters[alph_dec->filter_] != NULL);
878
for (y = first_row; y < last_row; ++y) {
879
WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);
880
prev_line = out;
881
out += stride;
882
}
883
alph_dec->prev_line_ = prev_line;
884
}
885
}
886
887
static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
888
// For vertical and gradient filtering, we need to decode the part above the
889
// crop_top row, in order to have the correct spatial predictors.
890
ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
891
const int top_row =
892
(alph_dec->filter_ == WEBP_FILTER_NONE ||
893
alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top
894
: dec->last_row_;
895
const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;
896
assert(last_row <= dec->io_->crop_bottom);
897
if (last_row > first_row) {
898
// Special method for paletted alpha data. We only process the cropped area.
899
const int width = dec->io_->width;
900
uint8_t* out = alph_dec->output_ + width * first_row;
901
const uint8_t* const in =
902
(uint8_t*)dec->pixels_ + dec->width_ * first_row;
903
VP8LTransform* const transform = &dec->transforms_[0];
904
assert(dec->next_transform_ == 1);
905
assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
906
VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,
907
in, out);
908
AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
909
}
910
dec->last_row_ = dec->last_out_row_ = last_row;
911
}
912
913
//------------------------------------------------------------------------------
914
// Helper functions for fast pattern copy (8b and 32b)
915
916
// cyclic rotation of pattern word
917
static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {
918
#if defined(WORDS_BIGENDIAN)
919
return ((V & 0xff000000u) >> 24) | (V << 8);
920
#else
921
return ((V & 0xffu) << 24) | (V >> 8);
922
#endif
923
}
924
925
// copy 1, 2 or 4-bytes pattern
926
static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,
927
int length, uint32_t pattern) {
928
int i;
929
// align 'dst' to 4-bytes boundary. Adjust the pattern along the way.
930
while ((uintptr_t)dst & 3) {
931
*dst++ = *src++;
932
pattern = Rotate8b(pattern);
933
--length;
934
}
935
// Copy the pattern 4 bytes at a time.
936
for (i = 0; i < (length >> 2); ++i) {
937
((uint32_t*)dst)[i] = pattern;
938
}
939
// Finish with left-overs. 'pattern' is still correctly positioned,
940
// so no Rotate8b() call is needed.
941
for (i <<= 2; i < length; ++i) {
942
dst[i] = src[i];
943
}
944
}
945
946
static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
947
const uint8_t* src = dst - dist;
948
if (length >= 8) {
949
uint32_t pattern = 0;
950
switch (dist) {
951
case 1:
952
pattern = src[0];
953
#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much
954
pattern |= pattern << 8;
955
pattern |= pattern << 16;
956
#elif defined(WEBP_USE_MIPS_DSP_R2)
957
__asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));
958
#else
959
pattern = 0x01010101u * pattern;
960
#endif
961
break;
962
case 2:
963
#if !defined(WORDS_BIGENDIAN)
964
memcpy(&pattern, src, sizeof(uint16_t));
965
#else
966
pattern = ((uint32_t)src[0] << 8) | src[1];
967
#endif
968
#if defined(__arm__) || defined(_M_ARM)
969
pattern |= pattern << 16;
970
#elif defined(WEBP_USE_MIPS_DSP_R2)
971
__asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));
972
#else
973
pattern = 0x00010001u * pattern;
974
#endif
975
break;
976
case 4:
977
memcpy(&pattern, src, sizeof(uint32_t));
978
break;
979
default:
980
goto Copy;
981
}
982
CopySmallPattern8b(src, dst, length, pattern);
983
return;
984
}
985
Copy:
986
if (dist >= length) { // no overlap -> use memcpy()
987
memcpy(dst, src, length * sizeof(*dst));
988
} else {
989
int i;
990
for (i = 0; i < length; ++i) dst[i] = src[i];
991
}
992
}
993
994
// copy pattern of 1 or 2 uint32_t's
995
static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,
996
uint32_t* dst,
997
int length, uint64_t pattern) {
998
int i;
999
if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.
1000
*dst++ = *src++;
1001
pattern = (pattern >> 32) | (pattern << 32);
1002
--length;
1003
}
1004
assert(0 == ((uintptr_t)dst & 7));
1005
for (i = 0; i < (length >> 1); ++i) {
1006
((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time.
1007
}
1008
if (length & 1) { // Finish with left-over.
1009
dst[i << 1] = src[i << 1];
1010
}
1011
}
1012
1013
static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,
1014
int dist, int length) {
1015
const uint32_t* const src = dst - dist;
1016
if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {
1017
uint64_t pattern;
1018
if (dist == 1) {
1019
pattern = (uint64_t)src[0];
1020
pattern |= pattern << 32;
1021
} else {
1022
memcpy(&pattern, src, sizeof(pattern));
1023
}
1024
CopySmallPattern32b(src, dst, length, pattern);
1025
} else if (dist >= length) { // no overlap
1026
memcpy(dst, src, length * sizeof(*dst));
1027
} else {
1028
int i;
1029
for (i = 0; i < length; ++i) dst[i] = src[i];
1030
}
1031
}
1032
1033
//------------------------------------------------------------------------------
1034
1035
static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
1036
int width, int height, int last_row) {
1037
int ok = 1;
1038
int row = dec->last_pixel_ / width;
1039
int col = dec->last_pixel_ % width;
1040
VP8LBitReader* const br = &dec->br_;
1041
VP8LMetadata* const hdr = &dec->hdr_;
1042
int pos = dec->last_pixel_; // current position
1043
const int end = width * height; // End of data
1044
const int last = width * last_row; // Last pixel to decode
1045
const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
1046
const int mask = hdr->huffman_mask_;
1047
const HTreeGroup* htree_group =
1048
(pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
1049
assert(pos <= end);
1050
assert(last_row <= height);
1051
assert(Is8bOptimizable(hdr));
1052
1053
while (!br->eos_ && pos < last) {
1054
int code;
1055
// Only update when changing tile.
1056
if ((col & mask) == 0) {
1057
htree_group = GetHtreeGroupForPos(hdr, col, row);
1058
}
1059
assert(htree_group != NULL);
1060
VP8LFillBitWindow(br);
1061
code = ReadSymbol(htree_group->htrees[GREEN], br);
1062
if (code < NUM_LITERAL_CODES) { // Literal
1063
data[pos] = code;
1064
++pos;
1065
++col;
1066
if (col >= width) {
1067
col = 0;
1068
++row;
1069
if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1070
ExtractPalettedAlphaRows(dec, row);
1071
}
1072
}
1073
} else if (code < len_code_limit) { // Backward reference
1074
int dist_code, dist;
1075
const int length_sym = code - NUM_LITERAL_CODES;
1076
const int length = GetCopyLength(length_sym, br);
1077
const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
1078
VP8LFillBitWindow(br);
1079
dist_code = GetCopyDistance(dist_symbol, br);
1080
dist = PlaneCodeToDistance(width, dist_code);
1081
if (pos >= dist && end - pos >= length) {
1082
CopyBlock8b(data + pos, dist, length);
1083
} else {
1084
ok = 0;
1085
goto End;
1086
}
1087
pos += length;
1088
col += length;
1089
while (col >= width) {
1090
col -= width;
1091
++row;
1092
if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1093
ExtractPalettedAlphaRows(dec, row);
1094
}
1095
}
1096
if (pos < last && (col & mask)) {
1097
htree_group = GetHtreeGroupForPos(hdr, col, row);
1098
}
1099
} else { // Not reached
1100
ok = 0;
1101
goto End;
1102
}
1103
br->eos_ = VP8LIsEndOfStream(br);
1104
}
1105
// Process the remaining rows corresponding to last row-block.
1106
ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);
1107
1108
End:
1109
br->eos_ = VP8LIsEndOfStream(br);
1110
if (!ok || (br->eos_ && pos < end)) {
1111
return VP8LSetError(
1112
dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR);
1113
}
1114
dec->last_pixel_ = pos;
1115
return ok;
1116
}
1117
1118
static void SaveState(VP8LDecoder* const dec, int last_pixel) {
1119
assert(dec->incremental_);
1120
dec->saved_br_ = dec->br_;
1121
dec->saved_last_pixel_ = last_pixel;
1122
if (dec->hdr_.color_cache_size_ > 0) {
1123
VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_);
1124
}
1125
}
1126
1127
static void RestoreState(VP8LDecoder* const dec) {
1128
assert(dec->br_.eos_);
1129
dec->status_ = VP8_STATUS_SUSPENDED;
1130
dec->br_ = dec->saved_br_;
1131
dec->last_pixel_ = dec->saved_last_pixel_;
1132
if (dec->hdr_.color_cache_size_ > 0) {
1133
VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_);
1134
}
1135
}
1136
1137
#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points
1138
static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
1139
int width, int height, int last_row,
1140
ProcessRowsFunc process_func) {
1141
int row = dec->last_pixel_ / width;
1142
int col = dec->last_pixel_ % width;
1143
VP8LBitReader* const br = &dec->br_;
1144
VP8LMetadata* const hdr = &dec->hdr_;
1145
uint32_t* src = data + dec->last_pixel_;
1146
uint32_t* last_cached = src;
1147
uint32_t* const src_end = data + width * height; // End of data
1148
uint32_t* const src_last = data + width * last_row; // Last pixel to decode
1149
const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
1150
const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
1151
int next_sync_row = dec->incremental_ ? row : 1 << 24;
1152
VP8LColorCache* const color_cache =
1153
(hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
1154
const int mask = hdr->huffman_mask_;
1155
const HTreeGroup* htree_group =
1156
(src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
1157
assert(dec->last_row_ < last_row);
1158
assert(src_last <= src_end);
1159
1160
while (src < src_last) {
1161
int code;
1162
if (row >= next_sync_row) {
1163
SaveState(dec, (int)(src - data));
1164
next_sync_row = row + SYNC_EVERY_N_ROWS;
1165
}
1166
// Only update when changing tile. Note we could use this test:
1167
// if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
1168
// but that's actually slower and needs storing the previous col/row.
1169
if ((col & mask) == 0) {
1170
htree_group = GetHtreeGroupForPos(hdr, col, row);
1171
}
1172
assert(htree_group != NULL);
1173
if (htree_group->is_trivial_code) {
1174
*src = htree_group->literal_arb;
1175
goto AdvanceByOne;
1176
}
1177
VP8LFillBitWindow(br);
1178
if (htree_group->use_packed_table) {
1179
code = ReadPackedSymbols(htree_group, br, src);
1180
if (VP8LIsEndOfStream(br)) break;
1181
if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;
1182
} else {
1183
code = ReadSymbol(htree_group->htrees[GREEN], br);
1184
}
1185
if (VP8LIsEndOfStream(br)) break;
1186
if (code < NUM_LITERAL_CODES) { // Literal
1187
if (htree_group->is_trivial_literal) {
1188
*src = htree_group->literal_arb | (code << 8);
1189
} else {
1190
int red, blue, alpha;
1191
red = ReadSymbol(htree_group->htrees[RED], br);
1192
VP8LFillBitWindow(br);
1193
blue = ReadSymbol(htree_group->htrees[BLUE], br);
1194
alpha = ReadSymbol(htree_group->htrees[ALPHA], br);
1195
if (VP8LIsEndOfStream(br)) break;
1196
*src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;
1197
}
1198
AdvanceByOne:
1199
++src;
1200
++col;
1201
if (col >= width) {
1202
col = 0;
1203
++row;
1204
if (process_func != NULL) {
1205
if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1206
process_func(dec, row);
1207
}
1208
}
1209
if (color_cache != NULL) {
1210
while (last_cached < src) {
1211
VP8LColorCacheInsert(color_cache, *last_cached++);
1212
}
1213
}
1214
}
1215
} else if (code < len_code_limit) { // Backward reference
1216
int dist_code, dist;
1217
const int length_sym = code - NUM_LITERAL_CODES;
1218
const int length = GetCopyLength(length_sym, br);
1219
const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
1220
VP8LFillBitWindow(br);
1221
dist_code = GetCopyDistance(dist_symbol, br);
1222
dist = PlaneCodeToDistance(width, dist_code);
1223
1224
if (VP8LIsEndOfStream(br)) break;
1225
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
1226
goto Error;
1227
} else {
1228
CopyBlock32b(src, dist, length);
1229
}
1230
src += length;
1231
col += length;
1232
while (col >= width) {
1233
col -= width;
1234
++row;
1235
if (process_func != NULL) {
1236
if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1237
process_func(dec, row);
1238
}
1239
}
1240
}
1241
// Because of the check done above (before 'src' was incremented by
1242
// 'length'), the following holds true.
1243
assert(src <= src_end);
1244
if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
1245
if (color_cache != NULL) {
1246
while (last_cached < src) {
1247
VP8LColorCacheInsert(color_cache, *last_cached++);
1248
}
1249
}
1250
} else if (code < color_cache_limit) { // Color cache
1251
const int key = code - len_code_limit;
1252
assert(color_cache != NULL);
1253
while (last_cached < src) {
1254
VP8LColorCacheInsert(color_cache, *last_cached++);
1255
}
1256
*src = VP8LColorCacheLookup(color_cache, key);
1257
goto AdvanceByOne;
1258
} else { // Not reached
1259
goto Error;
1260
}
1261
}
1262
1263
br->eos_ = VP8LIsEndOfStream(br);
1264
// In incremental decoding:
1265
// br->eos_ && src < src_last: if 'br' reached the end of the buffer and
1266
// 'src_last' has not been reached yet, there is not enough data. 'dec' has to
1267
// be reset until there is more data.
1268
// !br->eos_ && src < src_last: this cannot happen as either the buffer is
1269
// fully read, either enough has been read to reach 'src_last'.
1270
// src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go
1271
// beyond 'src_last' in case the image is cropped and an LZ77 goes further.
1272
// The buffer might have been enough or there is some left. 'br->eos_' does
1273
// not matter.
1274
assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last);
1275
if (dec->incremental_ && br->eos_ && src < src_last) {
1276
RestoreState(dec);
1277
} else if ((dec->incremental_ && src >= src_last) || !br->eos_) {
1278
// Process the remaining rows corresponding to last row-block.
1279
if (process_func != NULL) {
1280
process_func(dec, row > last_row ? last_row : row);
1281
}
1282
dec->status_ = VP8_STATUS_OK;
1283
dec->last_pixel_ = (int)(src - data); // end-of-scan marker
1284
} else {
1285
// if not incremental, and we are past the end of buffer (eos_=1), then this
1286
// is a real bitstream error.
1287
goto Error;
1288
}
1289
return 1;
1290
1291
Error:
1292
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1293
}
1294
1295
// -----------------------------------------------------------------------------
1296
// VP8LTransform
1297
1298
static void ClearTransform(VP8LTransform* const transform) {
1299
WebPSafeFree(transform->data_);
1300
transform->data_ = NULL;
1301
}
1302
1303
// For security reason, we need to remap the color map to span
1304
// the total possible bundled values, and not just the num_colors.
1305
static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
1306
int i;
1307
const int final_num_colors = 1 << (8 >> transform->bits_);
1308
uint32_t* const new_color_map =
1309
(uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
1310
sizeof(*new_color_map));
1311
if (new_color_map == NULL) {
1312
return 0;
1313
} else {
1314
uint8_t* const data = (uint8_t*)transform->data_;
1315
uint8_t* const new_data = (uint8_t*)new_color_map;
1316
new_color_map[0] = transform->data_[0];
1317
for (i = 4; i < 4 * num_colors; ++i) {
1318
// Equivalent to VP8LAddPixels(), on a byte-basis.
1319
new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
1320
}
1321
for (; i < 4 * final_num_colors; ++i) {
1322
new_data[i] = 0; // black tail.
1323
}
1324
WebPSafeFree(transform->data_);
1325
transform->data_ = new_color_map;
1326
}
1327
return 1;
1328
}
1329
1330
static int ReadTransform(int* const xsize, int const* ysize,
1331
VP8LDecoder* const dec) {
1332
int ok = 1;
1333
VP8LBitReader* const br = &dec->br_;
1334
VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
1335
const VP8LImageTransformType type =
1336
(VP8LImageTransformType)VP8LReadBits(br, 2);
1337
1338
// Each transform type can only be present once in the stream.
1339
if (dec->transforms_seen_ & (1U << type)) {
1340
return 0; // Already there, let's not accept the second same transform.
1341
}
1342
dec->transforms_seen_ |= (1U << type);
1343
1344
transform->type_ = type;
1345
transform->xsize_ = *xsize;
1346
transform->ysize_ = *ysize;
1347
transform->data_ = NULL;
1348
++dec->next_transform_;
1349
assert(dec->next_transform_ <= NUM_TRANSFORMS);
1350
1351
switch (type) {
1352
case PREDICTOR_TRANSFORM:
1353
case CROSS_COLOR_TRANSFORM:
1354
transform->bits_ =
1355
MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);
1356
ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
1357
transform->bits_),
1358
VP8LSubSampleSize(transform->ysize_,
1359
transform->bits_),
1360
/*is_level0=*/0, dec, &transform->data_);
1361
break;
1362
case COLOR_INDEXING_TRANSFORM: {
1363
const int num_colors = VP8LReadBits(br, 8) + 1;
1364
const int bits = (num_colors > 16) ? 0
1365
: (num_colors > 4) ? 1
1366
: (num_colors > 2) ? 2
1367
: 3;
1368
*xsize = VP8LSubSampleSize(transform->xsize_, bits);
1369
transform->bits_ = bits;
1370
ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec,
1371
&transform->data_);
1372
if (ok && !ExpandColorMap(num_colors, transform)) {
1373
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1374
}
1375
break;
1376
}
1377
case SUBTRACT_GREEN_TRANSFORM:
1378
break;
1379
default:
1380
assert(0); // can't happen
1381
break;
1382
}
1383
1384
return ok;
1385
}
1386
1387
// -----------------------------------------------------------------------------
1388
// VP8LMetadata
1389
1390
static void InitMetadata(VP8LMetadata* const hdr) {
1391
assert(hdr != NULL);
1392
memset(hdr, 0, sizeof(*hdr));
1393
}
1394
1395
static void ClearMetadata(VP8LMetadata* const hdr) {
1396
assert(hdr != NULL);
1397
1398
WebPSafeFree(hdr->huffman_image_);
1399
VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
1400
VP8LHtreeGroupsFree(hdr->htree_groups_);
1401
VP8LColorCacheClear(&hdr->color_cache_);
1402
VP8LColorCacheClear(&hdr->saved_color_cache_);
1403
InitMetadata(hdr);
1404
}
1405
1406
// -----------------------------------------------------------------------------
1407
// VP8LDecoder
1408
1409
VP8LDecoder* VP8LNew(void) {
1410
VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
1411
if (dec == NULL) return NULL;
1412
dec->status_ = VP8_STATUS_OK;
1413
dec->state_ = READ_DIM;
1414
1415
VP8LDspInit(); // Init critical function pointers.
1416
1417
return dec;
1418
}
1419
1420
// Resets the decoder in its initial state, reclaiming memory.
1421
// Preserves the dec->status_ value.
1422
static void VP8LClear(VP8LDecoder* const dec) {
1423
int i;
1424
if (dec == NULL) return;
1425
ClearMetadata(&dec->hdr_);
1426
1427
WebPSafeFree(dec->pixels_);
1428
dec->pixels_ = NULL;
1429
for (i = 0; i < dec->next_transform_; ++i) {
1430
ClearTransform(&dec->transforms_[i]);
1431
}
1432
dec->next_transform_ = 0;
1433
dec->transforms_seen_ = 0;
1434
1435
WebPSafeFree(dec->rescaler_memory);
1436
dec->rescaler_memory = NULL;
1437
1438
dec->output_ = NULL; // leave no trace behind
1439
}
1440
1441
void VP8LDelete(VP8LDecoder* const dec) {
1442
if (dec != NULL) {
1443
VP8LClear(dec);
1444
WebPSafeFree(dec);
1445
}
1446
}
1447
1448
static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
1449
VP8LMetadata* const hdr = &dec->hdr_;
1450
const int num_bits = hdr->huffman_subsample_bits_;
1451
dec->width_ = width;
1452
dec->height_ = height;
1453
1454
hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
1455
hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
1456
}
1457
1458
static int DecodeImageStream(int xsize, int ysize,
1459
int is_level0,
1460
VP8LDecoder* const dec,
1461
uint32_t** const decoded_data) {
1462
int ok = 1;
1463
int transform_xsize = xsize;
1464
int transform_ysize = ysize;
1465
VP8LBitReader* const br = &dec->br_;
1466
VP8LMetadata* const hdr = &dec->hdr_;
1467
uint32_t* data = NULL;
1468
int color_cache_bits = 0;
1469
1470
// Read the transforms (may recurse).
1471
if (is_level0) {
1472
while (ok && VP8LReadBits(br, 1)) {
1473
ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
1474
}
1475
}
1476
1477
// Color cache
1478
if (ok && VP8LReadBits(br, 1)) {
1479
color_cache_bits = VP8LReadBits(br, 4);
1480
ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
1481
if (!ok) {
1482
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1483
goto End;
1484
}
1485
}
1486
1487
// Read the Huffman codes (may recurse).
1488
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
1489
color_cache_bits, is_level0);
1490
if (!ok) {
1491
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1492
goto End;
1493
}
1494
1495
// Finish setting up the color-cache
1496
if (color_cache_bits > 0) {
1497
hdr->color_cache_size_ = 1 << color_cache_bits;
1498
if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
1499
ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1500
goto End;
1501
}
1502
} else {
1503
hdr->color_cache_size_ = 0;
1504
}
1505
UpdateDecoder(dec, transform_xsize, transform_ysize);
1506
1507
if (is_level0) { // level 0 complete
1508
dec->state_ = READ_HDR;
1509
goto End;
1510
}
1511
1512
{
1513
const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
1514
data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
1515
if (data == NULL) {
1516
ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1517
goto End;
1518
}
1519
}
1520
1521
// Use the Huffman trees to decode the LZ77 encoded data.
1522
ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
1523
transform_ysize, NULL);
1524
ok = ok && !br->eos_;
1525
1526
End:
1527
if (!ok) {
1528
WebPSafeFree(data);
1529
ClearMetadata(hdr);
1530
} else {
1531
if (decoded_data != NULL) {
1532
*decoded_data = data;
1533
} else {
1534
// We allocate image data in this function only for transforms. At level 0
1535
// (that is: not the transforms), we shouldn't have allocated anything.
1536
assert(data == NULL);
1537
assert(is_level0);
1538
}
1539
dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
1540
if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
1541
}
1542
return ok;
1543
}
1544
1545
//------------------------------------------------------------------------------
1546
// Allocate internal buffers dec->pixels_ and dec->argb_cache_.
1547
static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
1548
const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
1549
// Scratch buffer corresponding to top-prediction row for transforming the
1550
// first row in the row-blocks. Not needed for paletted alpha.
1551
const uint64_t cache_top_pixels = (uint16_t)final_width;
1552
// Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
1553
const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
1554
const uint64_t total_num_pixels =
1555
num_pixels + cache_top_pixels + cache_pixels;
1556
1557
assert(dec->width_ <= final_width);
1558
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
1559
if (dec->pixels_ == NULL) {
1560
dec->argb_cache_ = NULL; // for soundness
1561
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1562
}
1563
dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
1564
return 1;
1565
}
1566
1567
static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
1568
const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
1569
dec->argb_cache_ = NULL; // for soundness
1570
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
1571
if (dec->pixels_ == NULL) {
1572
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1573
}
1574
return 1;
1575
}
1576
1577
//------------------------------------------------------------------------------
1578
1579
// Special row-processing that only stores the alpha data.
1580
static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
1581
int cur_row = dec->last_row_;
1582
int num_rows = last_row - cur_row;
1583
const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;
1584
1585
assert(last_row <= dec->io_->crop_bottom);
1586
while (num_rows > 0) {
1587
const int num_rows_to_process =
1588
(num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;
1589
// Extract alpha (which is stored in the green plane).
1590
ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
1591
uint8_t* const output = alph_dec->output_;
1592
const int width = dec->io_->width; // the final width (!= dec->width_)
1593
const int cache_pixs = width * num_rows_to_process;
1594
uint8_t* const dst = output + width * cur_row;
1595
const uint32_t* const src = dec->argb_cache_;
1596
ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
1597
WebPExtractGreen(src, dst, cache_pixs);
1598
AlphaApplyFilter(alph_dec,
1599
cur_row, cur_row + num_rows_to_process, dst, width);
1600
num_rows -= num_rows_to_process;
1601
in += num_rows_to_process * dec->width_;
1602
cur_row += num_rows_to_process;
1603
}
1604
assert(cur_row == last_row);
1605
dec->last_row_ = dec->last_out_row_ = last_row;
1606
}
1607
1608
int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
1609
const uint8_t* const data, size_t data_size) {
1610
int ok = 0;
1611
VP8LDecoder* dec = VP8LNew();
1612
1613
if (dec == NULL) return 0;
1614
1615
assert(alph_dec != NULL);
1616
1617
dec->width_ = alph_dec->width_;
1618
dec->height_ = alph_dec->height_;
1619
dec->io_ = &alph_dec->io_;
1620
dec->io_->opaque = alph_dec;
1621
dec->io_->width = alph_dec->width_;
1622
dec->io_->height = alph_dec->height_;
1623
1624
dec->status_ = VP8_STATUS_OK;
1625
VP8LInitBitReader(&dec->br_, data, data_size);
1626
1627
if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1,
1628
dec, /*decoded_data=*/NULL)) {
1629
goto Err;
1630
}
1631
1632
// Special case: if alpha data uses only the color indexing transform and
1633
// doesn't use color cache (a frequent case), we will use DecodeAlphaData()
1634
// method that only needs allocation of 1 byte per pixel (alpha channel).
1635
if (dec->next_transform_ == 1 &&
1636
dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
1637
Is8bOptimizable(&dec->hdr_)) {
1638
alph_dec->use_8b_decode_ = 1;
1639
ok = AllocateInternalBuffers8b(dec);
1640
} else {
1641
// Allocate internal buffers (note that dec->width_ may have changed here).
1642
alph_dec->use_8b_decode_ = 0;
1643
ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
1644
}
1645
1646
if (!ok) goto Err;
1647
1648
// Only set here, once we are sure it is valid (to avoid thread races).
1649
alph_dec->vp8l_dec_ = dec;
1650
return 1;
1651
1652
Err:
1653
VP8LDelete(dec);
1654
return 0;
1655
}
1656
1657
int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
1658
VP8LDecoder* const dec = alph_dec->vp8l_dec_;
1659
assert(dec != NULL);
1660
assert(last_row <= dec->height_);
1661
1662
if (dec->last_row_ >= last_row) {
1663
return 1; // done
1664
}
1665
1666
if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing();
1667
1668
// Decode (with special row processing).
1669
return alph_dec->use_8b_decode_ ?
1670
DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
1671
last_row) :
1672
DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
1673
last_row, ExtractAlphaRows);
1674
}
1675
1676
//------------------------------------------------------------------------------
1677
1678
int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
1679
int width, height, has_alpha;
1680
1681
if (dec == NULL) return 0;
1682
if (io == NULL) {
1683
return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
1684
}
1685
1686
dec->io_ = io;
1687
dec->status_ = VP8_STATUS_OK;
1688
VP8LInitBitReader(&dec->br_, io->data, io->data_size);
1689
if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
1690
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1691
goto Error;
1692
}
1693
dec->state_ = READ_DIM;
1694
io->width = width;
1695
io->height = height;
1696
1697
if (!DecodeImageStream(width, height, /*is_level0=*/1, dec,
1698
/*decoded_data=*/NULL)) {
1699
goto Error;
1700
}
1701
return 1;
1702
1703
Error:
1704
VP8LClear(dec);
1705
assert(dec->status_ != VP8_STATUS_OK);
1706
return 0;
1707
}
1708
1709
int VP8LDecodeImage(VP8LDecoder* const dec) {
1710
VP8Io* io = NULL;
1711
WebPDecParams* params = NULL;
1712
1713
if (dec == NULL) return 0;
1714
1715
assert(dec->hdr_.huffman_tables_.root.start != NULL);
1716
assert(dec->hdr_.htree_groups_ != NULL);
1717
assert(dec->hdr_.num_htree_groups_ > 0);
1718
1719
io = dec->io_;
1720
assert(io != NULL);
1721
params = (WebPDecParams*)io->opaque;
1722
assert(params != NULL);
1723
1724
// Initialization.
1725
if (dec->state_ != READ_DATA) {
1726
dec->output_ = params->output;
1727
assert(dec->output_ != NULL);
1728
1729
if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
1730
VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
1731
goto Err;
1732
}
1733
1734
if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
1735
1736
#if !defined(WEBP_REDUCE_SIZE)
1737
if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
1738
#else
1739
if (io->use_scaling) {
1740
VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
1741
goto Err;
1742
}
1743
#endif
1744
if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
1745
// need the alpha-multiply functions for premultiplied output or rescaling
1746
WebPInitAlphaProcessing();
1747
}
1748
1749
if (!WebPIsRGBMode(dec->output_->colorspace)) {
1750
WebPInitConvertARGBToYUV();
1751
if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();
1752
}
1753
if (dec->incremental_) {
1754
if (dec->hdr_.color_cache_size_ > 0 &&
1755
dec->hdr_.saved_color_cache_.colors_ == NULL) {
1756
if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,
1757
dec->hdr_.color_cache_.hash_bits_)) {
1758
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1759
goto Err;
1760
}
1761
}
1762
}
1763
dec->state_ = READ_DATA;
1764
}
1765
1766
// Decode.
1767
if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
1768
io->crop_bottom, ProcessRows)) {
1769
goto Err;
1770
}
1771
1772
params->last_y = dec->last_out_row_;
1773
return 1;
1774
1775
Err:
1776
VP8LClear(dec);
1777
assert(dec->status_ != VP8_STATUS_OK);
1778
return 0;
1779
}
1780
1781
//------------------------------------------------------------------------------
1782
1783