Path: blob/master/thirdparty/libwebp/src/dec/vp8l_dec.c
21395 views
// Copyright 2012 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// main entry for the decoder10//11// Authors: Vikas Arora ([email protected])12// Jyrki Alakuijala ([email protected])1314#include <assert.h>15#include <stddef.h>16#include <stdlib.h>17#include <string.h>1819#include "src/dec/alphai_dec.h"20#include "src/dec/vp8_dec.h"21#include "src/dec/vp8li_dec.h"22#include "src/dec/webpi_dec.h"23#include "src/dsp/dsp.h"24#include "src/dsp/lossless.h"25#include "src/dsp/lossless_common.h"26#include "src/utils/bit_reader_utils.h"27#include "src/utils/color_cache_utils.h"28#include "src/utils/huffman_utils.h"29#include "src/utils/rescaler_utils.h"30#include "src/utils/utils.h"31#include "src/webp/decode.h"32#include "src/webp/format_constants.h"33#include "src/webp/types.h"3435#define NUM_ARGB_CACHE_ROWS 163637static const int kCodeLengthLiterals = 16;38static const int kCodeLengthRepeatCode = 16;39static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 };40static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };4142// -----------------------------------------------------------------------------43// Five Huffman codes are used at each meta code:44// 1. green + length prefix codes + color cache codes,45// 2. alpha,46// 3. red,47// 4. blue, and,48// 5. distance prefix codes.49typedef enum {50GREEN = 0,51RED = 1,52BLUE = 2,53ALPHA = 3,54DIST = 455} HuffIndex;5657static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {58NUM_LITERAL_CODES + NUM_LENGTH_CODES,59NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,60NUM_DISTANCE_CODES61};6263static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {640, 1, 1, 1, 065};6667#define NUM_CODE_LENGTH_CODES 1968static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {6917, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1570};7172#define CODE_TO_PLANE_CODES 12073static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {740x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,750x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,760x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,770x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,780x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,790x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,800x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,810x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,820x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,830x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,840x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,850x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x7086};8788// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha89// and distance alphabets are constant (256 for red, blue and alpha, 40 for90// distance) and lookup table sizes for them in worst case are 630 and 41091// respectively. Size of green alphabet depends on color cache size and is equal92// to 256 (green component values) + 24 (length prefix values)93// + color_cache_size (between 0 and 2048).94// All values computed for 8-bit first level lookup with Mark Adler's tool:95// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c96#define FIXED_TABLE_SIZE (630 * 3 + 410)97static const uint16_t kTableSize[12] = {98FIXED_TABLE_SIZE + 654,99FIXED_TABLE_SIZE + 656,100FIXED_TABLE_SIZE + 658,101FIXED_TABLE_SIZE + 662,102FIXED_TABLE_SIZE + 670,103FIXED_TABLE_SIZE + 686,104FIXED_TABLE_SIZE + 718,105FIXED_TABLE_SIZE + 782,106FIXED_TABLE_SIZE + 912,107FIXED_TABLE_SIZE + 1168,108FIXED_TABLE_SIZE + 1680,109FIXED_TABLE_SIZE + 2704110};111112static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {113// The oldest error reported takes precedence over the new one.114if (dec->status == VP8_STATUS_OK || dec->status == VP8_STATUS_SUSPENDED) {115dec->status = error;116}117return 0;118}119120static int DecodeImageStream(int xsize, int ysize,121int is_level0,122VP8LDecoder* const dec,123uint32_t** const decoded_data);124125//------------------------------------------------------------------------------126127int VP8LCheckSignature(const uint8_t* const data, size_t size) {128return (size >= VP8L_FRAME_HEADER_SIZE &&129data[0] == VP8L_MAGIC_BYTE &&130(data[4] >> 5) == 0); // version131}132133static int ReadImageInfo(VP8LBitReader* const br,134int* const width, int* const height,135int* const has_alpha) {136if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;137*width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;138*height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;139*has_alpha = VP8LReadBits(br, 1);140if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;141return !br->eos;142}143144int VP8LGetInfo(const uint8_t* data, size_t data_size,145int* const width, int* const height, int* const has_alpha) {146if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {147return 0; // not enough data148} else if (!VP8LCheckSignature(data, data_size)) {149return 0; // bad signature150} else {151int w, h, a;152VP8LBitReader br;153VP8LInitBitReader(&br, data, data_size);154if (!ReadImageInfo(&br, &w, &h, &a)) {155return 0;156}157if (width != NULL) *width = w;158if (height != NULL) *height = h;159if (has_alpha != NULL) *has_alpha = a;160return 1;161}162}163164//------------------------------------------------------------------------------165166static WEBP_INLINE int GetCopyDistance(int distance_symbol,167VP8LBitReader* const br) {168int extra_bits, offset;169if (distance_symbol < 4) {170return distance_symbol + 1;171}172extra_bits = (distance_symbol - 2) >> 1;173offset = (2 + (distance_symbol & 1)) << extra_bits;174return offset + VP8LReadBits(br, extra_bits) + 1;175}176177static WEBP_INLINE int GetCopyLength(int length_symbol,178VP8LBitReader* const br) {179// Length and distance prefixes are encoded the same way.180return GetCopyDistance(length_symbol, br);181}182183static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {184if (plane_code > CODE_TO_PLANE_CODES) {185return plane_code - CODE_TO_PLANE_CODES;186} else {187const int dist_code = kCodeToPlane[plane_code - 1];188const int yoffset = dist_code >> 4;189const int xoffset = 8 - (dist_code & 0xf);190const int dist = yoffset * xsize + xoffset;191return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small192}193}194195//------------------------------------------------------------------------------196// Decodes the next Huffman code from bit-stream.197// VP8LFillBitWindow(br) needs to be called at minimum every second call198// to ReadSymbol, in order to pre-fetch enough bits.199static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,200VP8LBitReader* const br) {201int nbits;202uint32_t val = VP8LPrefetchBits(br);203table += val & HUFFMAN_TABLE_MASK;204nbits = table->bits - HUFFMAN_TABLE_BITS;205if (nbits > 0) {206VP8LSetBitPos(br, br->bit_pos + HUFFMAN_TABLE_BITS);207val = VP8LPrefetchBits(br);208table += table->value;209table += val & ((1 << nbits) - 1);210}211VP8LSetBitPos(br, br->bit_pos + table->bits);212return table->value;213}214215// Reads packed symbol depending on GREEN channel216#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask)217#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES218static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,219VP8LBitReader* const br,220uint32_t* const dst) {221const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);222const HuffmanCode32 code = group->packed_table[val];223assert(group->use_packed_table);224if (code.bits < BITS_SPECIAL_MARKER) {225VP8LSetBitPos(br, br->bit_pos + code.bits);226*dst = code.value;227return PACKED_NON_LITERAL_CODE;228} else {229VP8LSetBitPos(br, br->bit_pos + code.bits - BITS_SPECIAL_MARKER);230assert(code.value >= NUM_LITERAL_CODES);231return code.value;232}233}234235static int AccumulateHCode(HuffmanCode hcode, int shift,236HuffmanCode32* const huff) {237huff->bits += hcode.bits;238huff->value |= (uint32_t)hcode.value << shift;239assert(huff->bits <= HUFFMAN_TABLE_BITS);240return hcode.bits;241}242243static void BuildPackedTable(HTreeGroup* const htree_group) {244uint32_t code;245for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {246uint32_t bits = code;247HuffmanCode32* const huff = &htree_group->packed_table[bits];248HuffmanCode hcode = htree_group->htrees[GREEN][bits];249if (hcode.value >= NUM_LITERAL_CODES) {250huff->bits = hcode.bits + BITS_SPECIAL_MARKER;251huff->value = hcode.value;252} else {253huff->bits = 0;254huff->value = 0;255bits >>= AccumulateHCode(hcode, 8, huff);256bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);257bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);258bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);259(void)bits;260}261}262}263264static int ReadHuffmanCodeLengths(265VP8LDecoder* const dec, const int* const code_length_code_lengths,266int num_symbols, int* const code_lengths) {267int ok = 0;268VP8LBitReader* const br = &dec->br;269int symbol;270int max_symbol;271int prev_code_len = DEFAULT_CODE_LENGTH;272HuffmanTables tables;273274if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||275!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,276code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {277goto End;278}279280if (VP8LReadBits(br, 1)) { // use length281const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);282max_symbol = 2 + VP8LReadBits(br, length_nbits);283if (max_symbol > num_symbols) {284goto End;285}286} else {287max_symbol = num_symbols;288}289290symbol = 0;291while (symbol < num_symbols) {292const HuffmanCode* p;293int code_len;294if (max_symbol-- == 0) break;295VP8LFillBitWindow(br);296p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];297VP8LSetBitPos(br, br->bit_pos + p->bits);298code_len = p->value;299if (code_len < kCodeLengthLiterals) {300code_lengths[symbol++] = code_len;301if (code_len != 0) prev_code_len = code_len;302} else {303const int use_prev = (code_len == kCodeLengthRepeatCode);304const int slot = code_len - kCodeLengthLiterals;305const int extra_bits = kCodeLengthExtraBits[slot];306const int repeat_offset = kCodeLengthRepeatOffsets[slot];307int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;308if (symbol + repeat > num_symbols) {309goto End;310} else {311const int length = use_prev ? prev_code_len : 0;312while (repeat-- > 0) code_lengths[symbol++] = length;313}314}315}316ok = 1;317318End:319VP8LHuffmanTablesDeallocate(&tables);320if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);321return ok;322}323324// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman325// tree.326static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,327int* const code_lengths,328HuffmanTables* const table) {329int ok = 0;330int size = 0;331VP8LBitReader* const br = &dec->br;332const int simple_code = VP8LReadBits(br, 1);333334memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));335336if (simple_code) { // Read symbols, codes & code lengths directly.337const int num_symbols = VP8LReadBits(br, 1) + 1;338const int first_symbol_len_code = VP8LReadBits(br, 1);339// The first code is either 1 bit or 8 bit code.340int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);341code_lengths[symbol] = 1;342// The second code (if present), is always 8 bits long.343if (num_symbols == 2) {344symbol = VP8LReadBits(br, 8);345code_lengths[symbol] = 1;346}347ok = 1;348} else { // Decode Huffman-coded code lengths.349int i;350int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };351const int num_codes = VP8LReadBits(br, 4) + 4;352assert(num_codes <= NUM_CODE_LENGTH_CODES);353354for (i = 0; i < num_codes; ++i) {355code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);356}357ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,358code_lengths);359}360361ok = ok && !br->eos;362if (ok) {363size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,364code_lengths, alphabet_size);365}366if (!ok || size == 0) {367return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);368}369return size;370}371372static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,373int color_cache_bits, int allow_recursion) {374int i;375VP8LBitReader* const br = &dec->br;376VP8LMetadata* const hdr = &dec->hdr;377uint32_t* huffman_image = NULL;378HTreeGroup* htree_groups = NULL;379HuffmanTables* huffman_tables = &hdr->huffman_tables;380int num_htree_groups = 1;381int num_htree_groups_max = 1;382int* mapping = NULL;383int ok = 0;384385// Check the table has been 0 initialized (through InitMetadata).386assert(huffman_tables->root.start == NULL);387assert(huffman_tables->curr_segment == NULL);388389if (allow_recursion && VP8LReadBits(br, 1)) {390// use meta Huffman codes.391const int huffman_precision =392MIN_HUFFMAN_BITS + VP8LReadBits(br, NUM_HUFFMAN_BITS);393const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);394const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);395const int huffman_pixs = huffman_xsize * huffman_ysize;396if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec,397&huffman_image)) {398goto Error;399}400hdr->huffman_subsample_bits = huffman_precision;401for (i = 0; i < huffman_pixs; ++i) {402// The huffman data is stored in red and green bytes.403const int group = (huffman_image[i] >> 8) & 0xffff;404huffman_image[i] = group;405if (group >= num_htree_groups_max) {406num_htree_groups_max = group + 1;407}408}409// Check the validity of num_htree_groups_max. If it seems too big, use a410// smaller value for later. This will prevent big memory allocations to end411// up with a bad bitstream anyway.412// The value of 1000 is totally arbitrary. We know that num_htree_groups_max413// is smaller than (1 << 16) and should be smaller than the number of pixels414// (though the format allows it to be bigger).415if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {416// Create a mapping from the used indices to the minimal set of used417// values [0, num_htree_groups)418mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));419if (mapping == NULL) {420VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);421goto Error;422}423// -1 means a value is unmapped, and therefore unused in the Huffman424// image.425memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));426for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {427// Get the current mapping for the group and remap the Huffman image.428int* const mapped_group = &mapping[huffman_image[i]];429if (*mapped_group == -1) *mapped_group = num_htree_groups++;430huffman_image[i] = *mapped_group;431}432} else {433num_htree_groups = num_htree_groups_max;434}435}436437if (br->eos) goto Error;438439if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,440num_htree_groups_max, mapping, dec,441huffman_tables, &htree_groups)) {442goto Error;443}444ok = 1;445446// All OK. Finalize pointers.447hdr->huffman_image = huffman_image;448hdr->num_htree_groups = num_htree_groups;449hdr->htree_groups = htree_groups;450451Error:452WebPSafeFree(mapping);453if (!ok) {454WebPSafeFree(huffman_image);455VP8LHuffmanTablesDeallocate(huffman_tables);456VP8LHtreeGroupsFree(htree_groups);457}458return ok;459}460461int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,462int num_htree_groups_max, const int* const mapping,463VP8LDecoder* const dec,464HuffmanTables* const huffman_tables,465HTreeGroup** const htree_groups) {466int i, j, ok = 0;467const int max_alphabet_size =468kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0);469const int table_size = kTableSize[color_cache_bits];470int* code_lengths = NULL;471472if ((mapping == NULL && num_htree_groups != num_htree_groups_max) ||473num_htree_groups > num_htree_groups_max) {474goto Error;475}476477code_lengths =478(int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));479*htree_groups = VP8LHtreeGroupsNew(num_htree_groups);480481if (*htree_groups == NULL || code_lengths == NULL ||482!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,483huffman_tables)) {484VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);485goto Error;486}487488for (i = 0; i < num_htree_groups_max; ++i) {489// If the index "i" is unused in the Huffman image, just make sure the490// coefficients are valid but do not store them.491if (mapping != NULL && mapping[i] == -1) {492for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {493int alphabet_size = kAlphabetSize[j];494if (j == 0 && color_cache_bits > 0) {495alphabet_size += (1 << color_cache_bits);496}497// Passing in NULL so that nothing gets filled.498if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {499goto Error;500}501}502} else {503HTreeGroup* const htree_group =504&(*htree_groups)[(mapping == NULL) ? i : mapping[i]];505HuffmanCode** const htrees = htree_group->htrees;506int size;507int total_size = 0;508int is_trivial_literal = 1;509int max_bits = 0;510for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {511int alphabet_size = kAlphabetSize[j];512if (j == 0 && color_cache_bits > 0) {513alphabet_size += (1 << color_cache_bits);514}515size =516ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);517htrees[j] = huffman_tables->curr_segment->curr_table;518if (size == 0) {519goto Error;520}521if (is_trivial_literal && kLiteralMap[j] == 1) {522is_trivial_literal = (htrees[j]->bits == 0);523}524total_size += htrees[j]->bits;525huffman_tables->curr_segment->curr_table += size;526if (j <= ALPHA) {527int local_max_bits = code_lengths[0];528int k;529for (k = 1; k < alphabet_size; ++k) {530if (code_lengths[k] > local_max_bits) {531local_max_bits = code_lengths[k];532}533}534max_bits += local_max_bits;535}536}537htree_group->is_trivial_literal = is_trivial_literal;538htree_group->is_trivial_code = 0;539if (is_trivial_literal) {540const int red = htrees[RED][0].value;541const int blue = htrees[BLUE][0].value;542const int alpha = htrees[ALPHA][0].value;543htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;544if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {545htree_group->is_trivial_code = 1;546htree_group->literal_arb |= htrees[GREEN][0].value << 8;547}548}549htree_group->use_packed_table =550!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);551if (htree_group->use_packed_table) BuildPackedTable(htree_group);552}553}554ok = 1;555556Error:557WebPSafeFree(code_lengths);558if (!ok) {559VP8LHuffmanTablesDeallocate(huffman_tables);560VP8LHtreeGroupsFree(*htree_groups);561*htree_groups = NULL;562}563return ok;564}565566//------------------------------------------------------------------------------567// Scaling.568569#if !defined(WEBP_REDUCE_SIZE)570static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {571const int num_channels = 4;572const int in_width = io->mb_w;573const int out_width = io->scaled_width;574const int in_height = io->mb_h;575const int out_height = io->scaled_height;576const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;577rescaler_t* work; // Rescaler work area.578const uint64_t scaled_data_size = (uint64_t)out_width;579uint32_t* scaled_data; // Temporary storage for scaled BGRA data.580const uint64_t memory_size = sizeof(*dec->rescaler) +581work_size * sizeof(*work) +582scaled_data_size * sizeof(*scaled_data);583uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));584if (memory == NULL) {585return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);586}587assert(dec->rescaler_memory == NULL);588dec->rescaler_memory = memory;589590dec->rescaler = (WebPRescaler*)memory;591memory += sizeof(*dec->rescaler);592work = (rescaler_t*)memory;593memory += work_size * sizeof(*work);594scaled_data = (uint32_t*)memory;595596if (!WebPRescalerInit(dec->rescaler, in_width, in_height,597(uint8_t*)scaled_data, out_width, out_height,5980, num_channels, work)) {599return 0;600}601return 1;602}603#endif // WEBP_REDUCE_SIZE604605//------------------------------------------------------------------------------606// Export to ARGB607608#if !defined(WEBP_REDUCE_SIZE)609610// We have special "export" function since we need to convert from BGRA611static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,612int rgba_stride, uint8_t* const rgba) {613uint32_t* const src = (uint32_t*)rescaler->dst;614uint8_t* dst = rgba;615const int dst_width = rescaler->dst_width;616int num_lines_out = 0;617while (WebPRescalerHasPendingOutput(rescaler)) {618WebPRescalerExportRow(rescaler);619WebPMultARGBRow(src, dst_width, 1);620VP8LConvertFromBGRA(src, dst_width, colorspace, dst);621dst += rgba_stride;622++num_lines_out;623}624return num_lines_out;625}626627// Emit scaled rows.628static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,629uint8_t* in, int in_stride, int mb_h,630uint8_t* const out, int out_stride) {631const WEBP_CSP_MODE colorspace = dec->output->colorspace;632int num_lines_in = 0;633int num_lines_out = 0;634while (num_lines_in < mb_h) {635uint8_t* const row_in = in + (ptrdiff_t)num_lines_in * in_stride;636uint8_t* const row_out = out + (ptrdiff_t)num_lines_out * out_stride;637const int lines_left = mb_h - num_lines_in;638const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);639int lines_imported;640assert(needed_lines > 0 && needed_lines <= lines_left);641WebPMultARGBRows(row_in, in_stride,642dec->rescaler->src_width, needed_lines, 0);643lines_imported =644WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);645assert(lines_imported == needed_lines);646num_lines_in += lines_imported;647num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);648}649return num_lines_out;650}651652#endif // WEBP_REDUCE_SIZE653654// Emit rows without any scaling.655static int EmitRows(WEBP_CSP_MODE colorspace,656const uint8_t* row_in, int in_stride,657int mb_w, int mb_h,658uint8_t* const out, int out_stride) {659int lines = mb_h;660uint8_t* row_out = out;661while (lines-- > 0) {662VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);663row_in += in_stride;664row_out += out_stride;665}666return mb_h; // Num rows out == num rows in.667}668669//------------------------------------------------------------------------------670// Export to YUVA671672static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,673const WebPDecBuffer* const output) {674const WebPYUVABuffer* const buf = &output->u.YUVA;675676// first, the luma plane677WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);678679// then U/V planes680{681uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;682uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;683// even lines: store values684// odd lines: average with previous values685WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));686}687// Lastly, store alpha if needed.688if (buf->a != NULL) {689uint8_t* const a = buf->a + y_pos * buf->a_stride;690#if defined(WORDS_BIGENDIAN)691WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);692#else693WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);694#endif695}696}697698static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {699WebPRescaler* const rescaler = dec->rescaler;700uint32_t* const src = (uint32_t*)rescaler->dst;701const int dst_width = rescaler->dst_width;702int num_lines_out = 0;703while (WebPRescalerHasPendingOutput(rescaler)) {704WebPRescalerExportRow(rescaler);705WebPMultARGBRow(src, dst_width, 1);706ConvertToYUVA(src, dst_width, y_pos, dec->output);707++y_pos;708++num_lines_out;709}710return num_lines_out;711}712713static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,714uint8_t* in, int in_stride, int mb_h) {715int num_lines_in = 0;716int y_pos = dec->last_out_row;717while (num_lines_in < mb_h) {718const int lines_left = mb_h - num_lines_in;719const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);720int lines_imported;721WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);722lines_imported =723WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);724assert(lines_imported == needed_lines);725num_lines_in += lines_imported;726in += needed_lines * in_stride;727y_pos += ExportYUVA(dec, y_pos);728}729return y_pos;730}731732static int EmitRowsYUVA(const VP8LDecoder* const dec,733const uint8_t* in, int in_stride,734int mb_w, int num_rows) {735int y_pos = dec->last_out_row;736while (num_rows-- > 0) {737ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output);738in += in_stride;739++y_pos;740}741return y_pos;742}743744//------------------------------------------------------------------------------745// Cropping.746747// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and748// crop options. Also updates the input data pointer, so that it points to the749// start of the cropped window. Note that pixels are in ARGB format even if750// 'in_data' is uint8_t*.751// Returns true if the crop window is not empty.752static int SetCropWindow(VP8Io* const io, int y_start, int y_end,753uint8_t** const in_data, int pixel_stride) {754assert(y_start < y_end);755assert(io->crop_left < io->crop_right);756if (y_end > io->crop_bottom) {757y_end = io->crop_bottom; // make sure we don't overflow on last row.758}759if (y_start < io->crop_top) {760const int delta = io->crop_top - y_start;761y_start = io->crop_top;762*in_data += delta * pixel_stride;763}764if (y_start >= y_end) return 0; // Crop window is empty.765766*in_data += io->crop_left * sizeof(uint32_t);767768io->mb_y = y_start - io->crop_top;769io->mb_w = io->crop_right - io->crop_left;770io->mb_h = y_end - y_start;771return 1; // Non-empty crop window.772}773774//------------------------------------------------------------------------------775776static WEBP_INLINE int GetMetaIndex(777const uint32_t* const image, int xsize, int bits, int x, int y) {778if (bits == 0) return 0;779return image[xsize * (y >> bits) + (x >> bits)];780}781782static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,783int x, int y) {784const int meta_index = GetMetaIndex(hdr->huffman_image, hdr->huffman_xsize,785hdr->huffman_subsample_bits, x, y);786assert(meta_index < hdr->num_htree_groups);787return hdr->htree_groups + meta_index;788}789790//------------------------------------------------------------------------------791// Main loop, with custom row-processing function792793typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);794795static void ApplyInverseTransforms(VP8LDecoder* const dec,796int start_row, int num_rows,797const uint32_t* const rows) {798int n = dec->next_transform;799const int cache_pixs = dec->width * num_rows;800const int end_row = start_row + num_rows;801const uint32_t* rows_in = rows;802uint32_t* const rows_out = dec->argb_cache;803804// Inverse transforms.805while (n-- > 0) {806VP8LTransform* const transform = &dec->transforms[n];807VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);808rows_in = rows_out;809}810if (rows_in != rows_out) {811// No transform called, hence just copy.812memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));813}814}815816// Processes (transforms, scales & color-converts) the rows decoded after the817// last call.818static void ProcessRows(VP8LDecoder* const dec, int row) {819const uint32_t* const rows = dec->pixels + dec->width * dec->last_row;820const int num_rows = row - dec->last_row;821822assert(row <= dec->io->crop_bottom);823// We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size824// of argb_cache), but we currently don't need more than that.825assert(num_rows <= NUM_ARGB_CACHE_ROWS);826if (num_rows > 0) { // Emit output.827VP8Io* const io = dec->io;828uint8_t* rows_data = (uint8_t*)dec->argb_cache;829const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA830ApplyInverseTransforms(dec, dec->last_row, num_rows, rows);831if (!SetCropWindow(io, dec->last_row, row, &rows_data, in_stride)) {832// Nothing to output (this time).833} else {834const WebPDecBuffer* const output = dec->output;835if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA836const WebPRGBABuffer* const buf = &output->u.RGBA;837uint8_t* const rgba =838buf->rgba + (ptrdiff_t)dec->last_out_row * buf->stride;839const int num_rows_out =840#if !defined(WEBP_REDUCE_SIZE)841io->use_scaling ?842EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,843rgba, buf->stride) :844#endif // WEBP_REDUCE_SIZE845EmitRows(output->colorspace, rows_data, in_stride,846io->mb_w, io->mb_h, rgba, buf->stride);847// Update 'last_out_row'.848dec->last_out_row += num_rows_out;849} else { // convert to YUVA850dec->last_out_row = io->use_scaling ?851EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :852EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);853}854assert(dec->last_out_row <= output->height);855}856}857858// Update 'last_row'.859dec->last_row = row;860assert(dec->last_row <= dec->height);861}862863// Row-processing for the special case when alpha data contains only one864// transform (color indexing), and trivial non-green literals.865static int Is8bOptimizable(const VP8LMetadata* const hdr) {866int i;867if (hdr->color_cache_size > 0) return 0;868// When the Huffman tree contains only one symbol, we can skip the869// call to ReadSymbol() for red/blue/alpha channels.870for (i = 0; i < hdr->num_htree_groups; ++i) {871HuffmanCode** const htrees = hdr->htree_groups[i].htrees;872if (htrees[RED][0].bits > 0) return 0;873if (htrees[BLUE][0].bits > 0) return 0;874if (htrees[ALPHA][0].bits > 0) return 0;875}876return 1;877}878879static void AlphaApplyFilter(ALPHDecoder* const alph_dec,880int first_row, int last_row,881uint8_t* out, int stride) {882if (alph_dec->filter != WEBP_FILTER_NONE) {883int y;884const uint8_t* prev_line = alph_dec->prev_line;885assert(WebPUnfilters[alph_dec->filter] != NULL);886for (y = first_row; y < last_row; ++y) {887WebPUnfilters[alph_dec->filter](prev_line, out, out, stride);888prev_line = out;889out += stride;890}891alph_dec->prev_line = prev_line;892}893}894895static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {896// For vertical and gradient filtering, we need to decode the part above the897// crop_top row, in order to have the correct spatial predictors.898ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io->opaque;899const int top_row =900(alph_dec->filter == WEBP_FILTER_NONE ||901alph_dec->filter == WEBP_FILTER_HORIZONTAL) ? dec->io->crop_top902: dec->last_row;903const int first_row = (dec->last_row < top_row) ? top_row : dec->last_row;904assert(last_row <= dec->io->crop_bottom);905if (last_row > first_row) {906// Special method for paletted alpha data. We only process the cropped area.907const int width = dec->io->width;908uint8_t* out = alph_dec->output + width * first_row;909const uint8_t* const in =910(uint8_t*)dec->pixels + dec->width * first_row;911VP8LTransform* const transform = &dec->transforms[0];912assert(dec->next_transform == 1);913assert(transform->type == COLOR_INDEXING_TRANSFORM);914VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,915in, out);916AlphaApplyFilter(alph_dec, first_row, last_row, out, width);917}918dec->last_row = dec->last_out_row = last_row;919}920921//------------------------------------------------------------------------------922// Helper functions for fast pattern copy (8b and 32b)923924// cyclic rotation of pattern word925static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {926#if defined(WORDS_BIGENDIAN)927return ((V & 0xff000000u) >> 24) | (V << 8);928#else929return ((V & 0xffu) << 24) | (V >> 8);930#endif931}932933// copy 1, 2 or 4-bytes pattern934static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,935int length, uint32_t pattern) {936int i;937// align 'dst' to 4-bytes boundary. Adjust the pattern along the way.938while ((uintptr_t)dst & 3) {939*dst++ = *src++;940pattern = Rotate8b(pattern);941--length;942}943// Copy the pattern 4 bytes at a time.944for (i = 0; i < (length >> 2); ++i) {945((uint32_t*)dst)[i] = pattern;946}947// Finish with left-overs. 'pattern' is still correctly positioned,948// so no Rotate8b() call is needed.949for (i <<= 2; i < length; ++i) {950dst[i] = src[i];951}952}953954static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {955const uint8_t* src = dst - dist;956if (length >= 8) {957uint32_t pattern = 0;958switch (dist) {959case 1:960pattern = src[0];961#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much962pattern |= pattern << 8;963pattern |= pattern << 16;964#elif defined(WEBP_USE_MIPS_DSP_R2)965__asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));966#else967pattern = 0x01010101u * pattern;968#endif969break;970case 2:971#if !defined(WORDS_BIGENDIAN)972memcpy(&pattern, src, sizeof(uint16_t));973#else974pattern = ((uint32_t)src[0] << 8) | src[1];975#endif976#if defined(__arm__) || defined(_M_ARM)977pattern |= pattern << 16;978#elif defined(WEBP_USE_MIPS_DSP_R2)979__asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));980#else981pattern = 0x00010001u * pattern;982#endif983break;984case 4:985memcpy(&pattern, src, sizeof(uint32_t));986break;987default:988goto Copy;989}990CopySmallPattern8b(src, dst, length, pattern);991return;992}993Copy:994if (dist >= length) { // no overlap -> use memcpy()995memcpy(dst, src, length * sizeof(*dst));996} else {997int i;998for (i = 0; i < length; ++i) dst[i] = src[i];999}1000}10011002// copy pattern of 1 or 2 uint32_t's1003static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,1004uint32_t* dst,1005int length, uint64_t pattern) {1006int i;1007if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.1008*dst++ = *src++;1009pattern = (pattern >> 32) | (pattern << 32);1010--length;1011}1012assert(0 == ((uintptr_t)dst & 7));1013for (i = 0; i < (length >> 1); ++i) {1014((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time.1015}1016if (length & 1) { // Finish with left-over.1017dst[i << 1] = src[i << 1];1018}1019}10201021static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,1022int dist, int length) {1023const uint32_t* const src = dst - dist;1024if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {1025uint64_t pattern;1026if (dist == 1) {1027pattern = (uint64_t)src[0];1028pattern |= pattern << 32;1029} else {1030memcpy(&pattern, src, sizeof(pattern));1031}1032CopySmallPattern32b(src, dst, length, pattern);1033} else if (dist >= length) { // no overlap1034memcpy(dst, src, length * sizeof(*dst));1035} else {1036int i;1037for (i = 0; i < length; ++i) dst[i] = src[i];1038}1039}10401041//------------------------------------------------------------------------------10421043static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,1044int width, int height, int last_row) {1045int ok = 1;1046int row = dec->last_pixel / width;1047int col = dec->last_pixel % width;1048VP8LBitReader* const br = &dec->br;1049VP8LMetadata* const hdr = &dec->hdr;1050int pos = dec->last_pixel; // current position1051const int end = width * height; // End of data1052const int last = width * last_row; // Last pixel to decode1053const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;1054const int mask = hdr->huffman_mask;1055const HTreeGroup* htree_group =1056(pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;1057assert(pos <= end);1058assert(last_row <= height);1059assert(Is8bOptimizable(hdr));10601061while (!br->eos && pos < last) {1062int code;1063// Only update when changing tile.1064if ((col & mask) == 0) {1065htree_group = GetHtreeGroupForPos(hdr, col, row);1066}1067assert(htree_group != NULL);1068VP8LFillBitWindow(br);1069code = ReadSymbol(htree_group->htrees[GREEN], br);1070if (code < NUM_LITERAL_CODES) { // Literal1071data[pos] = code;1072++pos;1073++col;1074if (col >= width) {1075col = 0;1076++row;1077if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1078ExtractPalettedAlphaRows(dec, row);1079}1080}1081} else if (code < len_code_limit) { // Backward reference1082int dist_code, dist;1083const int length_sym = code - NUM_LITERAL_CODES;1084const int length = GetCopyLength(length_sym, br);1085const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);1086VP8LFillBitWindow(br);1087dist_code = GetCopyDistance(dist_symbol, br);1088dist = PlaneCodeToDistance(width, dist_code);1089if (pos >= dist && end - pos >= length) {1090CopyBlock8b(data + pos, dist, length);1091} else {1092ok = 0;1093goto End;1094}1095pos += length;1096col += length;1097while (col >= width) {1098col -= width;1099++row;1100if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1101ExtractPalettedAlphaRows(dec, row);1102}1103}1104if (pos < last && (col & mask)) {1105htree_group = GetHtreeGroupForPos(hdr, col, row);1106}1107} else { // Not reached1108ok = 0;1109goto End;1110}1111br->eos = VP8LIsEndOfStream(br);1112}1113// Process the remaining rows corresponding to last row-block.1114ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);11151116End:1117br->eos = VP8LIsEndOfStream(br);1118if (!ok || (br->eos && pos < end)) {1119return VP8LSetError(1120dec, br->eos ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR);1121}1122dec->last_pixel = pos;1123return ok;1124}11251126static void SaveState(VP8LDecoder* const dec, int last_pixel) {1127assert(dec->incremental);1128dec->saved_br = dec->br;1129dec->saved_last_pixel = last_pixel;1130if (dec->hdr.color_cache_size > 0) {1131VP8LColorCacheCopy(&dec->hdr.color_cache, &dec->hdr.saved_color_cache);1132}1133}11341135static void RestoreState(VP8LDecoder* const dec) {1136assert(dec->br.eos);1137dec->status = VP8_STATUS_SUSPENDED;1138dec->br = dec->saved_br;1139dec->last_pixel = dec->saved_last_pixel;1140if (dec->hdr.color_cache_size > 0) {1141VP8LColorCacheCopy(&dec->hdr.saved_color_cache, &dec->hdr.color_cache);1142}1143}11441145#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points1146static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,1147int width, int height, int last_row,1148ProcessRowsFunc process_func) {1149int row = dec->last_pixel / width;1150int col = dec->last_pixel % width;1151VP8LBitReader* const br = &dec->br;1152VP8LMetadata* const hdr = &dec->hdr;1153uint32_t* src = data + dec->last_pixel;1154uint32_t* last_cached = src;1155uint32_t* const src_end = data + width * height; // End of data1156uint32_t* const src_last = data + width * last_row; // Last pixel to decode1157const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;1158const int color_cache_limit = len_code_limit + hdr->color_cache_size;1159int next_sync_row = dec->incremental ? row : 1 << 24;1160VP8LColorCache* const color_cache =1161(hdr->color_cache_size > 0) ? &hdr->color_cache : NULL;1162const int mask = hdr->huffman_mask;1163const HTreeGroup* htree_group =1164(src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;1165assert(dec->last_row < last_row);1166assert(src_last <= src_end);11671168while (src < src_last) {1169int code;1170if (row >= next_sync_row) {1171SaveState(dec, (int)(src - data));1172next_sync_row = row + SYNC_EVERY_N_ROWS;1173}1174// Only update when changing tile. Note we could use this test:1175// if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed1176// but that's actually slower and needs storing the previous col/row.1177if ((col & mask) == 0) {1178htree_group = GetHtreeGroupForPos(hdr, col, row);1179}1180assert(htree_group != NULL);1181if (htree_group->is_trivial_code) {1182*src = htree_group->literal_arb;1183goto AdvanceByOne;1184}1185VP8LFillBitWindow(br);1186if (htree_group->use_packed_table) {1187code = ReadPackedSymbols(htree_group, br, src);1188if (VP8LIsEndOfStream(br)) break;1189if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;1190} else {1191code = ReadSymbol(htree_group->htrees[GREEN], br);1192}1193if (VP8LIsEndOfStream(br)) break;1194if (code < NUM_LITERAL_CODES) { // Literal1195if (htree_group->is_trivial_literal) {1196*src = htree_group->literal_arb | (code << 8);1197} else {1198int red, blue, alpha;1199red = ReadSymbol(htree_group->htrees[RED], br);1200VP8LFillBitWindow(br);1201blue = ReadSymbol(htree_group->htrees[BLUE], br);1202alpha = ReadSymbol(htree_group->htrees[ALPHA], br);1203if (VP8LIsEndOfStream(br)) break;1204*src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;1205}1206AdvanceByOne:1207++src;1208++col;1209if (col >= width) {1210col = 0;1211++row;1212if (process_func != NULL) {1213if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1214process_func(dec, row);1215}1216}1217if (color_cache != NULL) {1218while (last_cached < src) {1219VP8LColorCacheInsert(color_cache, *last_cached++);1220}1221}1222}1223} else if (code < len_code_limit) { // Backward reference1224int dist_code, dist;1225const int length_sym = code - NUM_LITERAL_CODES;1226const int length = GetCopyLength(length_sym, br);1227const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);1228VP8LFillBitWindow(br);1229dist_code = GetCopyDistance(dist_symbol, br);1230dist = PlaneCodeToDistance(width, dist_code);12311232if (VP8LIsEndOfStream(br)) break;1233if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {1234goto Error;1235} else {1236CopyBlock32b(src, dist, length);1237}1238src += length;1239col += length;1240while (col >= width) {1241col -= width;1242++row;1243if (process_func != NULL) {1244if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1245process_func(dec, row);1246}1247}1248}1249// Because of the check done above (before 'src' was incremented by1250// 'length'), the following holds true.1251assert(src <= src_end);1252if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);1253if (color_cache != NULL) {1254while (last_cached < src) {1255VP8LColorCacheInsert(color_cache, *last_cached++);1256}1257}1258} else if (code < color_cache_limit) { // Color cache1259const int key = code - len_code_limit;1260assert(color_cache != NULL);1261while (last_cached < src) {1262VP8LColorCacheInsert(color_cache, *last_cached++);1263}1264*src = VP8LColorCacheLookup(color_cache, key);1265goto AdvanceByOne;1266} else { // Not reached1267goto Error;1268}1269}12701271br->eos = VP8LIsEndOfStream(br);1272// In incremental decoding:1273// br->eos && src < src_last: if 'br' reached the end of the buffer and1274// 'src_last' has not been reached yet, there is not enough data. 'dec' has to1275// be reset until there is more data.1276// !br->eos && src < src_last: this cannot happen as either the buffer is1277// fully read, either enough has been read to reach 'src_last'.1278// src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go1279// beyond 'src_last' in case the image is cropped and an LZ77 goes further.1280// The buffer might have been enough or there is some left. 'br->eos' does1281// not matter.1282assert(!dec->incremental || (br->eos && src < src_last) || src >= src_last);1283if (dec->incremental && br->eos && src < src_last) {1284RestoreState(dec);1285} else if ((dec->incremental && src >= src_last) || !br->eos) {1286// Process the remaining rows corresponding to last row-block.1287if (process_func != NULL) {1288process_func(dec, row > last_row ? last_row : row);1289}1290dec->status = VP8_STATUS_OK;1291dec->last_pixel = (int)(src - data); // end-of-scan marker1292} else {1293// if not incremental, and we are past the end of buffer (eos=1), then this1294// is a real bitstream error.1295goto Error;1296}1297return 1;12981299Error:1300return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1301}13021303// -----------------------------------------------------------------------------1304// VP8LTransform13051306static void ClearTransform(VP8LTransform* const transform) {1307WebPSafeFree(transform->data);1308transform->data = NULL;1309}13101311// For security reason, we need to remap the color map to span1312// the total possible bundled values, and not just the num_colors.1313static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {1314int i;1315const int final_num_colors = 1 << (8 >> transform->bits);1316uint32_t* const new_color_map =1317(uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,1318sizeof(*new_color_map));1319if (new_color_map == NULL) {1320return 0;1321} else {1322uint8_t* const data = (uint8_t*)transform->data;1323uint8_t* const new_data = (uint8_t*)new_color_map;1324new_color_map[0] = transform->data[0];1325for (i = 4; i < 4 * num_colors; ++i) {1326// Equivalent to VP8LAddPixels(), on a byte-basis.1327new_data[i] = (data[i] + new_data[i - 4]) & 0xff;1328}1329for (; i < 4 * final_num_colors; ++i) {1330new_data[i] = 0; // black tail.1331}1332WebPSafeFree(transform->data);1333transform->data = new_color_map;1334}1335return 1;1336}13371338static int ReadTransform(int* const xsize, int const* ysize,1339VP8LDecoder* const dec) {1340int ok = 1;1341VP8LBitReader* const br = &dec->br;1342VP8LTransform* transform = &dec->transforms[dec->next_transform];1343const VP8LImageTransformType type =1344(VP8LImageTransformType)VP8LReadBits(br, 2);13451346// Each transform type can only be present once in the stream.1347if (dec->transforms_seen & (1U << type)) {1348return 0; // Already there, let's not accept the second same transform.1349}1350dec->transforms_seen |= (1U << type);13511352transform->type = type;1353transform->xsize = *xsize;1354transform->ysize = *ysize;1355transform->data = NULL;1356++dec->next_transform;1357assert(dec->next_transform <= NUM_TRANSFORMS);13581359switch (type) {1360case PREDICTOR_TRANSFORM:1361case CROSS_COLOR_TRANSFORM:1362transform->bits =1363MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);1364ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize,1365transform->bits),1366VP8LSubSampleSize(transform->ysize,1367transform->bits),1368/*is_level0=*/0, dec, &transform->data);1369break;1370case COLOR_INDEXING_TRANSFORM: {1371const int num_colors = VP8LReadBits(br, 8) + 1;1372const int bits = (num_colors > 16) ? 01373: (num_colors > 4) ? 11374: (num_colors > 2) ? 21375: 3;1376*xsize = VP8LSubSampleSize(transform->xsize, bits);1377transform->bits = bits;1378ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec,1379&transform->data);1380if (ok && !ExpandColorMap(num_colors, transform)) {1381return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1382}1383break;1384}1385case SUBTRACT_GREEN_TRANSFORM:1386break;1387default:1388assert(0); // can't happen1389break;1390}13911392return ok;1393}13941395// -----------------------------------------------------------------------------1396// VP8LMetadata13971398static void InitMetadata(VP8LMetadata* const hdr) {1399assert(hdr != NULL);1400memset(hdr, 0, sizeof(*hdr));1401}14021403static void ClearMetadata(VP8LMetadata* const hdr) {1404assert(hdr != NULL);14051406WebPSafeFree(hdr->huffman_image);1407VP8LHuffmanTablesDeallocate(&hdr->huffman_tables);1408VP8LHtreeGroupsFree(hdr->htree_groups);1409VP8LColorCacheClear(&hdr->color_cache);1410VP8LColorCacheClear(&hdr->saved_color_cache);1411InitMetadata(hdr);1412}14131414// -----------------------------------------------------------------------------1415// VP8LDecoder14161417VP8LDecoder* VP8LNew(void) {1418VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));1419if (dec == NULL) return NULL;1420dec->status = VP8_STATUS_OK;1421dec->state = READ_DIM;14221423VP8LDspInit(); // Init critical function pointers.14241425return dec;1426}14271428// Resets the decoder in its initial state, reclaiming memory.1429// Preserves the dec->status value.1430static void VP8LClear(VP8LDecoder* const dec) {1431int i;1432if (dec == NULL) return;1433ClearMetadata(&dec->hdr);14341435WebPSafeFree(dec->pixels);1436dec->pixels = NULL;1437for (i = 0; i < dec->next_transform; ++i) {1438ClearTransform(&dec->transforms[i]);1439}1440dec->next_transform = 0;1441dec->transforms_seen = 0;14421443WebPSafeFree(dec->rescaler_memory);1444dec->rescaler_memory = NULL;14451446dec->output = NULL; // leave no trace behind1447}14481449void VP8LDelete(VP8LDecoder* const dec) {1450if (dec != NULL) {1451VP8LClear(dec);1452WebPSafeFree(dec);1453}1454}14551456static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {1457VP8LMetadata* const hdr = &dec->hdr;1458const int num_bits = hdr->huffman_subsample_bits;1459dec->width = width;1460dec->height = height;14611462hdr->huffman_xsize = VP8LSubSampleSize(width, num_bits);1463hdr->huffman_mask = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;1464}14651466static int DecodeImageStream(int xsize, int ysize,1467int is_level0,1468VP8LDecoder* const dec,1469uint32_t** const decoded_data) {1470int ok = 1;1471int transform_xsize = xsize;1472int transform_ysize = ysize;1473VP8LBitReader* const br = &dec->br;1474VP8LMetadata* const hdr = &dec->hdr;1475uint32_t* data = NULL;1476int color_cache_bits = 0;14771478// Read the transforms (may recurse).1479if (is_level0) {1480while (ok && VP8LReadBits(br, 1)) {1481ok = ReadTransform(&transform_xsize, &transform_ysize, dec);1482}1483}14841485// Color cache1486if (ok && VP8LReadBits(br, 1)) {1487color_cache_bits = VP8LReadBits(br, 4);1488ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);1489if (!ok) {1490VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1491goto End;1492}1493}14941495// Read the Huffman codes (may recurse).1496ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,1497color_cache_bits, is_level0);1498if (!ok) {1499VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1500goto End;1501}15021503// Finish setting up the color-cache1504if (color_cache_bits > 0) {1505hdr->color_cache_size = 1 << color_cache_bits;1506if (!VP8LColorCacheInit(&hdr->color_cache, color_cache_bits)) {1507ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1508goto End;1509}1510} else {1511hdr->color_cache_size = 0;1512}1513UpdateDecoder(dec, transform_xsize, transform_ysize);15141515if (is_level0) { // level 0 complete1516dec->state = READ_HDR;1517goto End;1518}15191520{1521const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;1522data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));1523if (data == NULL) {1524ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1525goto End;1526}1527}15281529// Use the Huffman trees to decode the LZ77 encoded data.1530ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,1531transform_ysize, NULL);1532ok = ok && !br->eos;15331534End:1535if (!ok) {1536WebPSafeFree(data);1537ClearMetadata(hdr);1538} else {1539if (decoded_data != NULL) {1540*decoded_data = data;1541} else {1542// We allocate image data in this function only for transforms. At level 01543// (that is: not the transforms), we shouldn't have allocated anything.1544assert(data == NULL);1545assert(is_level0);1546}1547dec->last_pixel = 0; // Reset for future DECODE_DATA_FUNC() calls.1548if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.1549}1550return ok;1551}15521553//------------------------------------------------------------------------------1554// Allocate internal buffers dec->pixels and dec->argb_cache.1555static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {1556const uint64_t num_pixels = (uint64_t)dec->width * dec->height;1557// Scratch buffer corresponding to top-prediction row for transforming the1558// first row in the row-blocks. Not needed for paletted alpha.1559const uint64_t cache_top_pixels = (uint16_t)final_width;1560// Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.1561const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;1562const uint64_t total_num_pixels =1563num_pixels + cache_top_pixels + cache_pixels;15641565assert(dec->width <= final_width);1566dec->pixels = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));1567if (dec->pixels == NULL) {1568dec->argb_cache = NULL; // for soundness1569return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1570}1571dec->argb_cache = dec->pixels + num_pixels + cache_top_pixels;1572return 1;1573}15741575static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {1576const uint64_t total_num_pixels = (uint64_t)dec->width * dec->height;1577dec->argb_cache = NULL; // for soundness1578dec->pixels = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));1579if (dec->pixels == NULL) {1580return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1581}1582return 1;1583}15841585//------------------------------------------------------------------------------15861587// Special row-processing that only stores the alpha data.1588static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {1589int cur_row = dec->last_row;1590int num_rows = last_row - cur_row;1591const uint32_t* in = dec->pixels + dec->width * cur_row;15921593assert(last_row <= dec->io->crop_bottom);1594while (num_rows > 0) {1595const int num_rows_to_process =1596(num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;1597// Extract alpha (which is stored in the green plane).1598ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io->opaque;1599uint8_t* const output = alph_dec->output;1600const int width = dec->io->width; // the final width (!= dec->width)1601const int cache_pixs = width * num_rows_to_process;1602uint8_t* const dst = output + width * cur_row;1603const uint32_t* const src = dec->argb_cache;1604ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);1605WebPExtractGreen(src, dst, cache_pixs);1606AlphaApplyFilter(alph_dec,1607cur_row, cur_row + num_rows_to_process, dst, width);1608num_rows -= num_rows_to_process;1609in += num_rows_to_process * dec->width;1610cur_row += num_rows_to_process;1611}1612assert(cur_row == last_row);1613dec->last_row = dec->last_out_row = last_row;1614}16151616int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,1617const uint8_t* const data, size_t data_size) {1618int ok = 0;1619VP8LDecoder* dec = VP8LNew();16201621if (dec == NULL) return 0;16221623assert(alph_dec != NULL);16241625dec->width = alph_dec->width;1626dec->height = alph_dec->height;1627dec->io = &alph_dec->io;1628dec->io->opaque = alph_dec;1629dec->io->width = alph_dec->width;1630dec->io->height = alph_dec->height;16311632dec->status = VP8_STATUS_OK;1633VP8LInitBitReader(&dec->br, data, data_size);16341635if (!DecodeImageStream(alph_dec->width, alph_dec->height, /*is_level0=*/1,1636dec, /*decoded_data=*/NULL)) {1637goto Err;1638}16391640// Special case: if alpha data uses only the color indexing transform and1641// doesn't use color cache (a frequent case), we will use DecodeAlphaData()1642// method that only needs allocation of 1 byte per pixel (alpha channel).1643if (dec->next_transform == 1 &&1644dec->transforms[0].type == COLOR_INDEXING_TRANSFORM &&1645Is8bOptimizable(&dec->hdr)) {1646alph_dec->use_8b_decode = 1;1647ok = AllocateInternalBuffers8b(dec);1648} else {1649// Allocate internal buffers (note that dec->width may have changed here).1650alph_dec->use_8b_decode = 0;1651ok = AllocateInternalBuffers32b(dec, alph_dec->width);1652}16531654if (!ok) goto Err;16551656// Only set here, once we are sure it is valid (to avoid thread races).1657alph_dec->vp8l_dec = dec;1658return 1;16591660Err:1661VP8LDelete(dec);1662return 0;1663}16641665int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {1666VP8LDecoder* const dec = alph_dec->vp8l_dec;1667assert(dec != NULL);1668assert(last_row <= dec->height);16691670if (dec->last_row >= last_row) {1671return 1; // done1672}16731674if (!alph_dec->use_8b_decode) WebPInitAlphaProcessing();16751676// Decode (with special row processing).1677return alph_dec->use_8b_decode ?1678DecodeAlphaData(dec, (uint8_t*)dec->pixels, dec->width, dec->height,1679last_row) :1680DecodeImageData(dec, dec->pixels, dec->width, dec->height,1681last_row, ExtractAlphaRows);1682}16831684//------------------------------------------------------------------------------16851686int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {1687int width, height, has_alpha;16881689if (dec == NULL) return 0;1690if (io == NULL) {1691return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);1692}16931694dec->io = io;1695dec->status = VP8_STATUS_OK;1696VP8LInitBitReader(&dec->br, io->data, io->data_size);1697if (!ReadImageInfo(&dec->br, &width, &height, &has_alpha)) {1698VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1699goto Error;1700}1701dec->state = READ_DIM;1702io->width = width;1703io->height = height;17041705if (!DecodeImageStream(width, height, /*is_level0=*/1, dec,1706/*decoded_data=*/NULL)) {1707goto Error;1708}1709return 1;17101711Error:1712VP8LClear(dec);1713assert(dec->status != VP8_STATUS_OK);1714return 0;1715}17161717int VP8LDecodeImage(VP8LDecoder* const dec) {1718VP8Io* io = NULL;1719WebPDecParams* params = NULL;17201721if (dec == NULL) return 0;17221723assert(dec->hdr.huffman_tables.root.start != NULL);1724assert(dec->hdr.htree_groups != NULL);1725assert(dec->hdr.num_htree_groups > 0);17261727io = dec->io;1728assert(io != NULL);1729params = (WebPDecParams*)io->opaque;1730assert(params != NULL);17311732// Initialization.1733if (dec->state != READ_DATA) {1734dec->output = params->output;1735assert(dec->output != NULL);17361737if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {1738VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);1739goto Err;1740}17411742if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;17431744#if !defined(WEBP_REDUCE_SIZE)1745if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;1746#else1747if (io->use_scaling) {1748VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);1749goto Err;1750}1751#endif1752if (io->use_scaling || WebPIsPremultipliedMode(dec->output->colorspace)) {1753// need the alpha-multiply functions for premultiplied output or rescaling1754WebPInitAlphaProcessing();1755}17561757if (!WebPIsRGBMode(dec->output->colorspace)) {1758WebPInitConvertARGBToYUV();1759if (dec->output->u.YUVA.a != NULL) WebPInitAlphaProcessing();1760}1761if (dec->incremental) {1762if (dec->hdr.color_cache_size > 0 &&1763dec->hdr.saved_color_cache.colors == NULL) {1764if (!VP8LColorCacheInit(&dec->hdr.saved_color_cache,1765dec->hdr.color_cache.hash_bits)) {1766VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1767goto Err;1768}1769}1770}1771dec->state = READ_DATA;1772}17731774// Decode.1775if (!DecodeImageData(dec, dec->pixels, dec->width, dec->height,1776io->crop_bottom, ProcessRows)) {1777goto Err;1778}17791780params->last_y = dec->last_out_row;1781return 1;17821783Err:1784VP8LClear(dec);1785assert(dec->status != VP8_STATUS_OK);1786return 0;1787}17881789//------------------------------------------------------------------------------179017911792