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