Path: blob/master/3rdparty/libwebp/src/dec/vp8l_dec.c
16358 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 <stdlib.h>1516#include "src/dec/alphai_dec.h"17#include "src/dec/vp8li_dec.h"18#include "src/dsp/dsp.h"19#include "src/dsp/lossless.h"20#include "src/dsp/lossless_common.h"21#include "src/dsp/yuv.h"22#include "src/utils/endian_inl_utils.h"23#include "src/utils/huffman_utils.h"24#include "src/utils/utils.h"2526#define NUM_ARGB_CACHE_ROWS 162728static const int kCodeLengthLiterals = 16;29static const int kCodeLengthRepeatCode = 16;30static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 };31static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };3233// -----------------------------------------------------------------------------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.40typedef enum {41GREEN = 0,42RED = 1,43BLUE = 2,44ALPHA = 3,45DIST = 446} HuffIndex;4748static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {49NUM_LITERAL_CODES + NUM_LENGTH_CODES,50NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,51NUM_DISTANCE_CODES52};5354static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {550, 1, 1, 1, 056};5758#define NUM_CODE_LENGTH_CODES 1959static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {6017, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1561};6263#define CODE_TO_PLANE_CODES 12064static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {650x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,660x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,670x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,680x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,690x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,700x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,710x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,720x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,730x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,740x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,750x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,760x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x7077};7879// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha80// and distance alphabets are constant (256 for red, blue and alpha, 40 for81// distance) and lookup table sizes for them in worst case are 630 and 41082// respectively. Size of green alphabet depends on color cache size and is equal83// 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.c87#define FIXED_TABLE_SIZE (630 * 3 + 410)88static const uint16_t kTableSize[12] = {89FIXED_TABLE_SIZE + 654,90FIXED_TABLE_SIZE + 656,91FIXED_TABLE_SIZE + 658,92FIXED_TABLE_SIZE + 662,93FIXED_TABLE_SIZE + 670,94FIXED_TABLE_SIZE + 686,95FIXED_TABLE_SIZE + 718,96FIXED_TABLE_SIZE + 782,97FIXED_TABLE_SIZE + 912,98FIXED_TABLE_SIZE + 1168,99FIXED_TABLE_SIZE + 1680,100FIXED_TABLE_SIZE + 2704101};102103static int DecodeImageStream(int xsize, int ysize,104int is_level0,105VP8LDecoder* const dec,106uint32_t** const decoded_data);107108//------------------------------------------------------------------------------109110int VP8LCheckSignature(const uint8_t* const data, size_t size) {111return (size >= VP8L_FRAME_HEADER_SIZE &&112data[0] == VP8L_MAGIC_BYTE &&113(data[4] >> 5) == 0); // version114}115116static int ReadImageInfo(VP8LBitReader* const br,117int* const width, int* const height,118int* const has_alpha) {119if (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);123if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;124return !br->eos_;125}126127int VP8LGetInfo(const uint8_t* data, size_t data_size,128int* const width, int* const height, int* const has_alpha) {129if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {130return 0; // not enough data131} else if (!VP8LCheckSignature(data, data_size)) {132return 0; // bad signature133} else {134int w, h, a;135VP8LBitReader br;136VP8LInitBitReader(&br, data, data_size);137if (!ReadImageInfo(&br, &w, &h, &a)) {138return 0;139}140if (width != NULL) *width = w;141if (height != NULL) *height = h;142if (has_alpha != NULL) *has_alpha = a;143return 1;144}145}146147//------------------------------------------------------------------------------148149static WEBP_INLINE int GetCopyDistance(int distance_symbol,150VP8LBitReader* const br) {151int extra_bits, offset;152if (distance_symbol < 4) {153return distance_symbol + 1;154}155extra_bits = (distance_symbol - 2) >> 1;156offset = (2 + (distance_symbol & 1)) << extra_bits;157return offset + VP8LReadBits(br, extra_bits) + 1;158}159160static WEBP_INLINE int GetCopyLength(int length_symbol,161VP8LBitReader* const br) {162// Length and distance prefixes are encoded the same way.163return GetCopyDistance(length_symbol, br);164}165166static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {167if (plane_code > CODE_TO_PLANE_CODES) {168return plane_code - CODE_TO_PLANE_CODES;169} else {170const int dist_code = kCodeToPlane[plane_code - 1];171const int yoffset = dist_code >> 4;172const int xoffset = 8 - (dist_code & 0xf);173const int dist = yoffset * xsize + xoffset;174return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small175}176}177178//------------------------------------------------------------------------------179// Decodes the next Huffman code from bit-stream.180// FillBitWindow(br) needs to be called at minimum every second call181// to ReadSymbol, in order to pre-fetch enough bits.182static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,183VP8LBitReader* const br) {184int nbits;185uint32_t val = VP8LPrefetchBits(br);186table += val & HUFFMAN_TABLE_MASK;187nbits = table->bits - HUFFMAN_TABLE_BITS;188if (nbits > 0) {189VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS);190val = VP8LPrefetchBits(br);191table += table->value;192table += val & ((1 << nbits) - 1);193}194VP8LSetBitPos(br, br->bit_pos_ + table->bits);195return table->value;196}197198// Reads packed symbol depending on GREEN channel199#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask)200#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES201static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,202VP8LBitReader* const br,203uint32_t* const dst) {204const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);205const HuffmanCode32 code = group->packed_table[val];206assert(group->use_packed_table);207if (code.bits < BITS_SPECIAL_MARKER) {208VP8LSetBitPos(br, br->bit_pos_ + code.bits);209*dst = code.value;210return PACKED_NON_LITERAL_CODE;211} else {212VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER);213assert(code.value >= NUM_LITERAL_CODES);214return code.value;215}216}217218static int AccumulateHCode(HuffmanCode hcode, int shift,219HuffmanCode32* const huff) {220huff->bits += hcode.bits;221huff->value |= (uint32_t)hcode.value << shift;222assert(huff->bits <= HUFFMAN_TABLE_BITS);223return hcode.bits;224}225226static void BuildPackedTable(HTreeGroup* const htree_group) {227uint32_t code;228for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {229uint32_t bits = code;230HuffmanCode32* const huff = &htree_group->packed_table[bits];231HuffmanCode hcode = htree_group->htrees[GREEN][bits];232if (hcode.value >= NUM_LITERAL_CODES) {233huff->bits = hcode.bits + BITS_SPECIAL_MARKER;234huff->value = hcode.value;235} else {236huff->bits = 0;237huff->value = 0;238bits >>= AccumulateHCode(hcode, 8, huff);239bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);240bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);241bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);242(void)bits;243}244}245}246247static int ReadHuffmanCodeLengths(248VP8LDecoder* const dec, const int* const code_length_code_lengths,249int num_symbols, int* const code_lengths) {250int ok = 0;251VP8LBitReader* const br = &dec->br_;252int symbol;253int max_symbol;254int prev_code_len = DEFAULT_CODE_LENGTH;255HuffmanCode table[1 << LENGTHS_TABLE_BITS];256257if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,258code_length_code_lengths,259NUM_CODE_LENGTH_CODES)) {260goto End;261}262263if (VP8LReadBits(br, 1)) { // use length264const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);265max_symbol = 2 + VP8LReadBits(br, length_nbits);266if (max_symbol > num_symbols) {267goto End;268}269} else {270max_symbol = num_symbols;271}272273symbol = 0;274while (symbol < num_symbols) {275const HuffmanCode* p;276int code_len;277if (max_symbol-- == 0) break;278VP8LFillBitWindow(br);279p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];280VP8LSetBitPos(br, br->bit_pos_ + p->bits);281code_len = p->value;282if (code_len < kCodeLengthLiterals) {283code_lengths[symbol++] = code_len;284if (code_len != 0) prev_code_len = code_len;285} else {286const int use_prev = (code_len == kCodeLengthRepeatCode);287const int slot = code_len - kCodeLengthLiterals;288const int extra_bits = kCodeLengthExtraBits[slot];289const int repeat_offset = kCodeLengthRepeatOffsets[slot];290int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;291if (symbol + repeat > num_symbols) {292goto End;293} else {294const int length = use_prev ? prev_code_len : 0;295while (repeat-- > 0) code_lengths[symbol++] = length;296}297}298}299ok = 1;300301End:302if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;303return ok;304}305306// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman307// tree.308static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,309int* const code_lengths, HuffmanCode* const table) {310int ok = 0;311int size = 0;312VP8LBitReader* const br = &dec->br_;313const int simple_code = VP8LReadBits(br, 1);314315memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));316317if (simple_code) { // Read symbols, codes & code lengths directly.318const int num_symbols = VP8LReadBits(br, 1) + 1;319const int first_symbol_len_code = VP8LReadBits(br, 1);320// The first code is either 1 bit or 8 bit code.321int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);322code_lengths[symbol] = 1;323// The second code (if present), is always 8 bit long.324if (num_symbols == 2) {325symbol = VP8LReadBits(br, 8);326code_lengths[symbol] = 1;327}328ok = 1;329} else { // Decode Huffman-coded code lengths.330int i;331int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };332const int num_codes = VP8LReadBits(br, 4) + 4;333if (num_codes > NUM_CODE_LENGTH_CODES) {334dec->status_ = VP8_STATUS_BITSTREAM_ERROR;335return 0;336}337338for (i = 0; i < num_codes; ++i) {339code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);340}341ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,342code_lengths);343}344345ok = ok && !br->eos_;346if (ok) {347size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,348code_lengths, alphabet_size);349}350if (!ok || size == 0) {351dec->status_ = VP8_STATUS_BITSTREAM_ERROR;352return 0;353}354return size;355}356357static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,358int color_cache_bits, int allow_recursion) {359int i, j;360VP8LBitReader* const br = &dec->br_;361VP8LMetadata* const hdr = &dec->hdr_;362uint32_t* huffman_image = NULL;363HTreeGroup* htree_groups = NULL;364HuffmanCode* huffman_tables = NULL;365HuffmanCode* next = NULL;366int num_htree_groups = 1;367int max_alphabet_size = 0;368int* code_lengths = NULL;369const int table_size = kTableSize[color_cache_bits];370371if (allow_recursion && VP8LReadBits(br, 1)) {372// use meta Huffman codes.373const int huffman_precision = VP8LReadBits(br, 3) + 2;374const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);375const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);376const int huffman_pixs = huffman_xsize * huffman_ysize;377if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,378&huffman_image)) {379goto Error;380}381hdr->huffman_subsample_bits_ = huffman_precision;382for (i = 0; i < huffman_pixs; ++i) {383// The huffman data is stored in red and green bytes.384const int group = (huffman_image[i] >> 8) & 0xffff;385huffman_image[i] = group;386if (group >= num_htree_groups) {387num_htree_groups = group + 1;388}389}390}391392if (br->eos_) goto Error;393394// Find maximum alphabet size for the htree group.395for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {396int alphabet_size = kAlphabetSize[j];397if (j == 0 && color_cache_bits > 0) {398alphabet_size += 1 << color_cache_bits;399}400if (max_alphabet_size < alphabet_size) {401max_alphabet_size = alphabet_size;402}403}404405huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,406sizeof(*huffman_tables));407htree_groups = VP8LHtreeGroupsNew(num_htree_groups);408code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,409sizeof(*code_lengths));410411if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {412dec->status_ = VP8_STATUS_OUT_OF_MEMORY;413goto Error;414}415416next = huffman_tables;417for (i = 0; i < num_htree_groups; ++i) {418HTreeGroup* const htree_group = &htree_groups[i];419HuffmanCode** const htrees = htree_group->htrees;420int size;421int total_size = 0;422int is_trivial_literal = 1;423int max_bits = 0;424for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {425int alphabet_size = kAlphabetSize[j];426htrees[j] = next;427if (j == 0 && color_cache_bits > 0) {428alphabet_size += 1 << color_cache_bits;429}430size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);431if (size == 0) {432goto Error;433}434if (is_trivial_literal && kLiteralMap[j] == 1) {435is_trivial_literal = (next->bits == 0);436}437total_size += next->bits;438next += size;439if (j <= ALPHA) {440int local_max_bits = code_lengths[0];441int k;442for (k = 1; k < alphabet_size; ++k) {443if (code_lengths[k] > local_max_bits) {444local_max_bits = code_lengths[k];445}446}447max_bits += local_max_bits;448}449}450htree_group->is_trivial_literal = is_trivial_literal;451htree_group->is_trivial_code = 0;452if (is_trivial_literal) {453const int red = htrees[RED][0].value;454const int blue = htrees[BLUE][0].value;455const int alpha = htrees[ALPHA][0].value;456htree_group->literal_arb =457((uint32_t)alpha << 24) | (red << 16) | blue;458if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {459htree_group->is_trivial_code = 1;460htree_group->literal_arb |= htrees[GREEN][0].value << 8;461}462}463htree_group->use_packed_table = !htree_group->is_trivial_code &&464(max_bits < HUFFMAN_PACKED_BITS);465if (htree_group->use_packed_table) BuildPackedTable(htree_group);466}467WebPSafeFree(code_lengths);468469// All OK. Finalize pointers and return.470hdr->huffman_image_ = huffman_image;471hdr->num_htree_groups_ = num_htree_groups;472hdr->htree_groups_ = htree_groups;473hdr->huffman_tables_ = huffman_tables;474return 1;475476Error:477WebPSafeFree(code_lengths);478WebPSafeFree(huffman_image);479WebPSafeFree(huffman_tables);480VP8LHtreeGroupsFree(htree_groups);481return 0;482}483484//------------------------------------------------------------------------------485// Scaling.486487#if !defined(WEBP_REDUCE_SIZE)488static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {489const int num_channels = 4;490const int in_width = io->mb_w;491const int out_width = io->scaled_width;492const int in_height = io->mb_h;493const int out_height = io->scaled_height;494const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;495rescaler_t* work; // Rescaler work area.496const uint64_t scaled_data_size = (uint64_t)out_width;497uint32_t* scaled_data; // Temporary storage for scaled BGRA data.498const uint64_t memory_size = sizeof(*dec->rescaler) +499work_size * sizeof(*work) +500scaled_data_size * sizeof(*scaled_data);501uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));502if (memory == NULL) {503dec->status_ = VP8_STATUS_OUT_OF_MEMORY;504return 0;505}506assert(dec->rescaler_memory == NULL);507dec->rescaler_memory = memory;508509dec->rescaler = (WebPRescaler*)memory;510memory += sizeof(*dec->rescaler);511work = (rescaler_t*)memory;512memory += work_size * sizeof(*work);513scaled_data = (uint32_t*)memory;514515WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,516out_width, out_height, 0, num_channels, work);517return 1;518}519#endif // WEBP_REDUCE_SIZE520521//------------------------------------------------------------------------------522// Export to ARGB523524#if !defined(WEBP_REDUCE_SIZE)525526// We have special "export" function since we need to convert from BGRA527static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,528int rgba_stride, uint8_t* const rgba) {529uint32_t* const src = (uint32_t*)rescaler->dst;530const int dst_width = rescaler->dst_width;531int num_lines_out = 0;532while (WebPRescalerHasPendingOutput(rescaler)) {533uint8_t* const dst = rgba + num_lines_out * rgba_stride;534WebPRescalerExportRow(rescaler);535WebPMultARGBRow(src, dst_width, 1);536VP8LConvertFromBGRA(src, dst_width, colorspace, dst);537++num_lines_out;538}539return num_lines_out;540}541542// Emit scaled rows.543static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,544uint8_t* in, int in_stride, int mb_h,545uint8_t* const out, int out_stride) {546const WEBP_CSP_MODE colorspace = dec->output_->colorspace;547int num_lines_in = 0;548int num_lines_out = 0;549while (num_lines_in < mb_h) {550uint8_t* const row_in = in + num_lines_in * in_stride;551uint8_t* const row_out = out + num_lines_out * out_stride;552const int lines_left = mb_h - num_lines_in;553const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);554int lines_imported;555assert(needed_lines > 0 && needed_lines <= lines_left);556WebPMultARGBRows(row_in, in_stride,557dec->rescaler->src_width, needed_lines, 0);558lines_imported =559WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);560assert(lines_imported == needed_lines);561num_lines_in += lines_imported;562num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);563}564return num_lines_out;565}566567#endif // WEBP_REDUCE_SIZE568569// Emit rows without any scaling.570static int EmitRows(WEBP_CSP_MODE colorspace,571const uint8_t* row_in, int in_stride,572int mb_w, int mb_h,573uint8_t* const out, int out_stride) {574int lines = mb_h;575uint8_t* row_out = out;576while (lines-- > 0) {577VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);578row_in += in_stride;579row_out += out_stride;580}581return mb_h; // Num rows out == num rows in.582}583584//------------------------------------------------------------------------------585// Export to YUVA586587static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,588const WebPDecBuffer* const output) {589const WebPYUVABuffer* const buf = &output->u.YUVA;590591// first, the luma plane592WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);593594// then U/V planes595{596uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;597uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;598// even lines: store values599// odd lines: average with previous values600WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));601}602// Lastly, store alpha if needed.603if (buf->a != NULL) {604uint8_t* const a = buf->a + y_pos * buf->a_stride;605#if defined(WORDS_BIGENDIAN)606WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);607#else608WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);609#endif610}611}612613static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {614WebPRescaler* const rescaler = dec->rescaler;615uint32_t* const src = (uint32_t*)rescaler->dst;616const int dst_width = rescaler->dst_width;617int num_lines_out = 0;618while (WebPRescalerHasPendingOutput(rescaler)) {619WebPRescalerExportRow(rescaler);620WebPMultARGBRow(src, dst_width, 1);621ConvertToYUVA(src, dst_width, y_pos, dec->output_);622++y_pos;623++num_lines_out;624}625return num_lines_out;626}627628static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,629uint8_t* in, int in_stride, int mb_h) {630int num_lines_in = 0;631int y_pos = dec->last_out_row_;632while (num_lines_in < mb_h) {633const int lines_left = mb_h - num_lines_in;634const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);635int lines_imported;636WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);637lines_imported =638WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);639assert(lines_imported == needed_lines);640num_lines_in += lines_imported;641in += needed_lines * in_stride;642y_pos += ExportYUVA(dec, y_pos);643}644return y_pos;645}646647static int EmitRowsYUVA(const VP8LDecoder* const dec,648const uint8_t* in, int in_stride,649int mb_w, int num_rows) {650int y_pos = dec->last_out_row_;651while (num_rows-- > 0) {652ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);653in += in_stride;654++y_pos;655}656return y_pos;657}658659//------------------------------------------------------------------------------660// Cropping.661662// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and663// crop options. Also updates the input data pointer, so that it points to the664// start of the cropped window. Note that pixels are in ARGB format even if665// 'in_data' is uint8_t*.666// Returns true if the crop window is not empty.667static int SetCropWindow(VP8Io* const io, int y_start, int y_end,668uint8_t** const in_data, int pixel_stride) {669assert(y_start < y_end);670assert(io->crop_left < io->crop_right);671if (y_end > io->crop_bottom) {672y_end = io->crop_bottom; // make sure we don't overflow on last row.673}674if (y_start < io->crop_top) {675const int delta = io->crop_top - y_start;676y_start = io->crop_top;677*in_data += delta * pixel_stride;678}679if (y_start >= y_end) return 0; // Crop window is empty.680681*in_data += io->crop_left * sizeof(uint32_t);682683io->mb_y = y_start - io->crop_top;684io->mb_w = io->crop_right - io->crop_left;685io->mb_h = y_end - y_start;686return 1; // Non-empty crop window.687}688689//------------------------------------------------------------------------------690691static WEBP_INLINE int GetMetaIndex(692const uint32_t* const image, int xsize, int bits, int x, int y) {693if (bits == 0) return 0;694return image[xsize * (y >> bits) + (x >> bits)];695}696697static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,698int x, int y) {699const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,700hdr->huffman_subsample_bits_, x, y);701assert(meta_index < hdr->num_htree_groups_);702return hdr->htree_groups_ + meta_index;703}704705//------------------------------------------------------------------------------706// Main loop, with custom row-processing function707708typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);709710static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,711const uint32_t* const rows) {712int n = dec->next_transform_;713const int cache_pixs = dec->width_ * num_rows;714const int start_row = dec->last_row_;715const int end_row = start_row + num_rows;716const uint32_t* rows_in = rows;717uint32_t* const rows_out = dec->argb_cache_;718719// Inverse transforms.720while (n-- > 0) {721VP8LTransform* const transform = &dec->transforms_[n];722VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);723rows_in = rows_out;724}725if (rows_in != rows_out) {726// No transform called, hence just copy.727memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));728}729}730731// Processes (transforms, scales & color-converts) the rows decoded after the732// last call.733static void ProcessRows(VP8LDecoder* const dec, int row) {734const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;735const int num_rows = row - dec->last_row_;736737assert(row <= dec->io_->crop_bottom);738// We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size739// of argb_cache_), but we currently don't need more than that.740assert(num_rows <= NUM_ARGB_CACHE_ROWS);741if (num_rows > 0) { // Emit output.742VP8Io* const io = dec->io_;743uint8_t* rows_data = (uint8_t*)dec->argb_cache_;744const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA745746ApplyInverseTransforms(dec, num_rows, rows);747if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {748// Nothing to output (this time).749} else {750const WebPDecBuffer* const output = dec->output_;751if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA752const WebPRGBABuffer* const buf = &output->u.RGBA;753uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;754const int num_rows_out =755#if !defined(WEBP_REDUCE_SIZE)756io->use_scaling ?757EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,758rgba, buf->stride) :759#endif // WEBP_REDUCE_SIZE760EmitRows(output->colorspace, rows_data, in_stride,761io->mb_w, io->mb_h, rgba, buf->stride);762// Update 'last_out_row_'.763dec->last_out_row_ += num_rows_out;764} else { // convert to YUVA765dec->last_out_row_ = io->use_scaling ?766EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :767EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);768}769assert(dec->last_out_row_ <= output->height);770}771}772773// Update 'last_row_'.774dec->last_row_ = row;775assert(dec->last_row_ <= dec->height_);776}777778// Row-processing for the special case when alpha data contains only one779// transform (color indexing), and trivial non-green literals.780static int Is8bOptimizable(const VP8LMetadata* const hdr) {781int i;782if (hdr->color_cache_size_ > 0) return 0;783// When the Huffman tree contains only one symbol, we can skip the784// call to ReadSymbol() for red/blue/alpha channels.785for (i = 0; i < hdr->num_htree_groups_; ++i) {786HuffmanCode** const htrees = hdr->htree_groups_[i].htrees;787if (htrees[RED][0].bits > 0) return 0;788if (htrees[BLUE][0].bits > 0) return 0;789if (htrees[ALPHA][0].bits > 0) return 0;790}791return 1;792}793794static void AlphaApplyFilter(ALPHDecoder* const alph_dec,795int first_row, int last_row,796uint8_t* out, int stride) {797if (alph_dec->filter_ != WEBP_FILTER_NONE) {798int y;799const uint8_t* prev_line = alph_dec->prev_line_;800assert(WebPUnfilters[alph_dec->filter_] != NULL);801for (y = first_row; y < last_row; ++y) {802WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);803prev_line = out;804out += stride;805}806alph_dec->prev_line_ = prev_line;807}808}809810static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {811// For vertical and gradient filtering, we need to decode the part above the812// crop_top row, in order to have the correct spatial predictors.813ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;814const int top_row =815(alph_dec->filter_ == WEBP_FILTER_NONE ||816alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top817: dec->last_row_;818const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;819assert(last_row <= dec->io_->crop_bottom);820if (last_row > first_row) {821// Special method for paletted alpha data. We only process the cropped area.822const int width = dec->io_->width;823uint8_t* out = alph_dec->output_ + width * first_row;824const uint8_t* const in =825(uint8_t*)dec->pixels_ + dec->width_ * first_row;826VP8LTransform* const transform = &dec->transforms_[0];827assert(dec->next_transform_ == 1);828assert(transform->type_ == COLOR_INDEXING_TRANSFORM);829VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,830in, out);831AlphaApplyFilter(alph_dec, first_row, last_row, out, width);832}833dec->last_row_ = dec->last_out_row_ = last_row;834}835836//------------------------------------------------------------------------------837// Helper functions for fast pattern copy (8b and 32b)838839// cyclic rotation of pattern word840static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {841#if defined(WORDS_BIGENDIAN)842return ((V & 0xff000000u) >> 24) | (V << 8);843#else844return ((V & 0xffu) << 24) | (V >> 8);845#endif846}847848// copy 1, 2 or 4-bytes pattern849static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,850int length, uint32_t pattern) {851int i;852// align 'dst' to 4-bytes boundary. Adjust the pattern along the way.853while ((uintptr_t)dst & 3) {854*dst++ = *src++;855pattern = Rotate8b(pattern);856--length;857}858// Copy the pattern 4 bytes at a time.859for (i = 0; i < (length >> 2); ++i) {860((uint32_t*)dst)[i] = pattern;861}862// Finish with left-overs. 'pattern' is still correctly positioned,863// so no Rotate8b() call is needed.864for (i <<= 2; i < length; ++i) {865dst[i] = src[i];866}867}868869static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {870const uint8_t* src = dst - dist;871if (length >= 8) {872uint32_t pattern = 0;873switch (dist) {874case 1:875pattern = src[0];876#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much877pattern |= pattern << 8;878pattern |= pattern << 16;879#elif defined(WEBP_USE_MIPS_DSP_R2)880__asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));881#else882pattern = 0x01010101u * pattern;883#endif884break;885case 2:886memcpy(&pattern, src, sizeof(uint16_t));887#if defined(__arm__) || defined(_M_ARM)888pattern |= pattern << 16;889#elif defined(WEBP_USE_MIPS_DSP_R2)890__asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));891#else892pattern = 0x00010001u * pattern;893#endif894break;895case 4:896memcpy(&pattern, src, sizeof(uint32_t));897break;898default:899goto Copy;900break;901}902CopySmallPattern8b(src, dst, length, pattern);903return;904}905Copy:906if (dist >= length) { // no overlap -> use memcpy()907memcpy(dst, src, length * sizeof(*dst));908} else {909int i;910for (i = 0; i < length; ++i) dst[i] = src[i];911}912}913914// copy pattern of 1 or 2 uint32_t's915static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,916uint32_t* dst,917int length, uint64_t pattern) {918int i;919if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.920*dst++ = *src++;921pattern = (pattern >> 32) | (pattern << 32);922--length;923}924assert(0 == ((uintptr_t)dst & 7));925for (i = 0; i < (length >> 1); ++i) {926((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time.927}928if (length & 1) { // Finish with left-over.929dst[i << 1] = src[i << 1];930}931}932933static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,934int dist, int length) {935const uint32_t* const src = dst - dist;936if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {937uint64_t pattern;938if (dist == 1) {939pattern = (uint64_t)src[0];940pattern |= pattern << 32;941} else {942memcpy(&pattern, src, sizeof(pattern));943}944CopySmallPattern32b(src, dst, length, pattern);945} else if (dist >= length) { // no overlap946memcpy(dst, src, length * sizeof(*dst));947} else {948int i;949for (i = 0; i < length; ++i) dst[i] = src[i];950}951}952953//------------------------------------------------------------------------------954955static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,956int width, int height, int last_row) {957int ok = 1;958int row = dec->last_pixel_ / width;959int col = dec->last_pixel_ % width;960VP8LBitReader* const br = &dec->br_;961VP8LMetadata* const hdr = &dec->hdr_;962int pos = dec->last_pixel_; // current position963const int end = width * height; // End of data964const int last = width * last_row; // Last pixel to decode965const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;966const int mask = hdr->huffman_mask_;967const HTreeGroup* htree_group =968(pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;969assert(pos <= end);970assert(last_row <= height);971assert(Is8bOptimizable(hdr));972973while (!br->eos_ && pos < last) {974int code;975// Only update when changing tile.976if ((col & mask) == 0) {977htree_group = GetHtreeGroupForPos(hdr, col, row);978}979assert(htree_group != NULL);980VP8LFillBitWindow(br);981code = ReadSymbol(htree_group->htrees[GREEN], br);982if (code < NUM_LITERAL_CODES) { // Literal983data[pos] = code;984++pos;985++col;986if (col >= width) {987col = 0;988++row;989if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {990ExtractPalettedAlphaRows(dec, row);991}992}993} else if (code < len_code_limit) { // Backward reference994int dist_code, dist;995const int length_sym = code - NUM_LITERAL_CODES;996const int length = GetCopyLength(length_sym, br);997const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);998VP8LFillBitWindow(br);999dist_code = GetCopyDistance(dist_symbol, br);1000dist = PlaneCodeToDistance(width, dist_code);1001if (pos >= dist && end - pos >= length) {1002CopyBlock8b(data + pos, dist, length);1003} else {1004ok = 0;1005goto End;1006}1007pos += length;1008col += length;1009while (col >= width) {1010col -= width;1011++row;1012if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1013ExtractPalettedAlphaRows(dec, row);1014}1015}1016if (pos < last && (col & mask)) {1017htree_group = GetHtreeGroupForPos(hdr, col, row);1018}1019} else { // Not reached1020ok = 0;1021goto End;1022}1023br->eos_ = VP8LIsEndOfStream(br);1024}1025// Process the remaining rows corresponding to last row-block.1026ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);10271028End:1029br->eos_ = VP8LIsEndOfStream(br);1030if (!ok || (br->eos_ && pos < end)) {1031ok = 0;1032dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED1033: VP8_STATUS_BITSTREAM_ERROR;1034} else {1035dec->last_pixel_ = pos;1036}1037return ok;1038}10391040static void SaveState(VP8LDecoder* const dec, int last_pixel) {1041assert(dec->incremental_);1042dec->saved_br_ = dec->br_;1043dec->saved_last_pixel_ = last_pixel;1044if (dec->hdr_.color_cache_size_ > 0) {1045VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_);1046}1047}10481049static void RestoreState(VP8LDecoder* const dec) {1050assert(dec->br_.eos_);1051dec->status_ = VP8_STATUS_SUSPENDED;1052dec->br_ = dec->saved_br_;1053dec->last_pixel_ = dec->saved_last_pixel_;1054if (dec->hdr_.color_cache_size_ > 0) {1055VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_);1056}1057}10581059#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points1060static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,1061int width, int height, int last_row,1062ProcessRowsFunc process_func) {1063int row = dec->last_pixel_ / width;1064int col = dec->last_pixel_ % width;1065VP8LBitReader* const br = &dec->br_;1066VP8LMetadata* const hdr = &dec->hdr_;1067uint32_t* src = data + dec->last_pixel_;1068uint32_t* last_cached = src;1069uint32_t* const src_end = data + width * height; // End of data1070uint32_t* const src_last = data + width * last_row; // Last pixel to decode1071const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;1072const int color_cache_limit = len_code_limit + hdr->color_cache_size_;1073int next_sync_row = dec->incremental_ ? row : 1 << 24;1074VP8LColorCache* const color_cache =1075(hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;1076const int mask = hdr->huffman_mask_;1077const HTreeGroup* htree_group =1078(src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;1079assert(dec->last_row_ < last_row);1080assert(src_last <= src_end);10811082while (src < src_last) {1083int code;1084if (row >= next_sync_row) {1085SaveState(dec, (int)(src - data));1086next_sync_row = row + SYNC_EVERY_N_ROWS;1087}1088// Only update when changing tile. Note we could use this test:1089// if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed1090// but that's actually slower and needs storing the previous col/row.1091if ((col & mask) == 0) {1092htree_group = GetHtreeGroupForPos(hdr, col, row);1093}1094assert(htree_group != NULL);1095if (htree_group->is_trivial_code) {1096*src = htree_group->literal_arb;1097goto AdvanceByOne;1098}1099VP8LFillBitWindow(br);1100if (htree_group->use_packed_table) {1101code = ReadPackedSymbols(htree_group, br, src);1102if (VP8LIsEndOfStream(br)) break;1103if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;1104} else {1105code = ReadSymbol(htree_group->htrees[GREEN], br);1106}1107if (VP8LIsEndOfStream(br)) break;1108if (code < NUM_LITERAL_CODES) { // Literal1109if (htree_group->is_trivial_literal) {1110*src = htree_group->literal_arb | (code << 8);1111} else {1112int red, blue, alpha;1113red = ReadSymbol(htree_group->htrees[RED], br);1114VP8LFillBitWindow(br);1115blue = ReadSymbol(htree_group->htrees[BLUE], br);1116alpha = ReadSymbol(htree_group->htrees[ALPHA], br);1117if (VP8LIsEndOfStream(br)) break;1118*src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;1119}1120AdvanceByOne:1121++src;1122++col;1123if (col >= width) {1124col = 0;1125++row;1126if (process_func != NULL) {1127if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1128process_func(dec, row);1129}1130}1131if (color_cache != NULL) {1132while (last_cached < src) {1133VP8LColorCacheInsert(color_cache, *last_cached++);1134}1135}1136}1137} else if (code < len_code_limit) { // Backward reference1138int dist_code, dist;1139const int length_sym = code - NUM_LITERAL_CODES;1140const int length = GetCopyLength(length_sym, br);1141const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);1142VP8LFillBitWindow(br);1143dist_code = GetCopyDistance(dist_symbol, br);1144dist = PlaneCodeToDistance(width, dist_code);1145if (VP8LIsEndOfStream(br)) break;1146if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {1147goto Error;1148} else {1149CopyBlock32b(src, dist, length);1150}1151src += length;1152col += length;1153while (col >= width) {1154col -= width;1155++row;1156if (process_func != NULL) {1157if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1158process_func(dec, row);1159}1160}1161}1162// Because of the check done above (before 'src' was incremented by1163// 'length'), the following holds true.1164assert(src <= src_end);1165if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);1166if (color_cache != NULL) {1167while (last_cached < src) {1168VP8LColorCacheInsert(color_cache, *last_cached++);1169}1170}1171} else if (code < color_cache_limit) { // Color cache1172const int key = code - len_code_limit;1173assert(color_cache != NULL);1174while (last_cached < src) {1175VP8LColorCacheInsert(color_cache, *last_cached++);1176}1177*src = VP8LColorCacheLookup(color_cache, key);1178goto AdvanceByOne;1179} else { // Not reached1180goto Error;1181}1182}11831184br->eos_ = VP8LIsEndOfStream(br);1185if (dec->incremental_ && br->eos_ && src < src_end) {1186RestoreState(dec);1187} else if (!br->eos_) {1188// Process the remaining rows corresponding to last row-block.1189if (process_func != NULL) {1190process_func(dec, row > last_row ? last_row : row);1191}1192dec->status_ = VP8_STATUS_OK;1193dec->last_pixel_ = (int)(src - data); // end-of-scan marker1194} else {1195// if not incremental, and we are past the end of buffer (eos_=1), then this1196// is a real bitstream error.1197goto Error;1198}1199return 1;12001201Error:1202dec->status_ = VP8_STATUS_BITSTREAM_ERROR;1203return 0;1204}12051206// -----------------------------------------------------------------------------1207// VP8LTransform12081209static void ClearTransform(VP8LTransform* const transform) {1210WebPSafeFree(transform->data_);1211transform->data_ = NULL;1212}12131214// For security reason, we need to remap the color map to span1215// the total possible bundled values, and not just the num_colors.1216static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {1217int i;1218const int final_num_colors = 1 << (8 >> transform->bits_);1219uint32_t* const new_color_map =1220(uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,1221sizeof(*new_color_map));1222if (new_color_map == NULL) {1223return 0;1224} else {1225uint8_t* const data = (uint8_t*)transform->data_;1226uint8_t* const new_data = (uint8_t*)new_color_map;1227new_color_map[0] = transform->data_[0];1228for (i = 4; i < 4 * num_colors; ++i) {1229// Equivalent to AddPixelEq(), on a byte-basis.1230new_data[i] = (data[i] + new_data[i - 4]) & 0xff;1231}1232for (; i < 4 * final_num_colors; ++i) {1233new_data[i] = 0; // black tail.1234}1235WebPSafeFree(transform->data_);1236transform->data_ = new_color_map;1237}1238return 1;1239}12401241static int ReadTransform(int* const xsize, int const* ysize,1242VP8LDecoder* const dec) {1243int ok = 1;1244VP8LBitReader* const br = &dec->br_;1245VP8LTransform* transform = &dec->transforms_[dec->next_transform_];1246const VP8LImageTransformType type =1247(VP8LImageTransformType)VP8LReadBits(br, 2);12481249// Each transform type can only be present once in the stream.1250if (dec->transforms_seen_ & (1U << type)) {1251return 0; // Already there, let's not accept the second same transform.1252}1253dec->transforms_seen_ |= (1U << type);12541255transform->type_ = type;1256transform->xsize_ = *xsize;1257transform->ysize_ = *ysize;1258transform->data_ = NULL;1259++dec->next_transform_;1260assert(dec->next_transform_ <= NUM_TRANSFORMS);12611262switch (type) {1263case PREDICTOR_TRANSFORM:1264case CROSS_COLOR_TRANSFORM:1265transform->bits_ = VP8LReadBits(br, 3) + 2;1266ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,1267transform->bits_),1268VP8LSubSampleSize(transform->ysize_,1269transform->bits_),12700, dec, &transform->data_);1271break;1272case COLOR_INDEXING_TRANSFORM: {1273const int num_colors = VP8LReadBits(br, 8) + 1;1274const int bits = (num_colors > 16) ? 01275: (num_colors > 4) ? 11276: (num_colors > 2) ? 21277: 3;1278*xsize = VP8LSubSampleSize(transform->xsize_, bits);1279transform->bits_ = bits;1280ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);1281ok = ok && ExpandColorMap(num_colors, transform);1282break;1283}1284case SUBTRACT_GREEN:1285break;1286default:1287assert(0); // can't happen1288break;1289}12901291return ok;1292}12931294// -----------------------------------------------------------------------------1295// VP8LMetadata12961297static void InitMetadata(VP8LMetadata* const hdr) {1298assert(hdr != NULL);1299memset(hdr, 0, sizeof(*hdr));1300}13011302static void ClearMetadata(VP8LMetadata* const hdr) {1303assert(hdr != NULL);13041305WebPSafeFree(hdr->huffman_image_);1306WebPSafeFree(hdr->huffman_tables_);1307VP8LHtreeGroupsFree(hdr->htree_groups_);1308VP8LColorCacheClear(&hdr->color_cache_);1309VP8LColorCacheClear(&hdr->saved_color_cache_);1310InitMetadata(hdr);1311}13121313// -----------------------------------------------------------------------------1314// VP8LDecoder13151316VP8LDecoder* VP8LNew(void) {1317VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));1318if (dec == NULL) return NULL;1319dec->status_ = VP8_STATUS_OK;1320dec->state_ = READ_DIM;13211322VP8LDspInit(); // Init critical function pointers.13231324return dec;1325}13261327void VP8LClear(VP8LDecoder* const dec) {1328int i;1329if (dec == NULL) return;1330ClearMetadata(&dec->hdr_);13311332WebPSafeFree(dec->pixels_);1333dec->pixels_ = NULL;1334for (i = 0; i < dec->next_transform_; ++i) {1335ClearTransform(&dec->transforms_[i]);1336}1337dec->next_transform_ = 0;1338dec->transforms_seen_ = 0;13391340WebPSafeFree(dec->rescaler_memory);1341dec->rescaler_memory = NULL;13421343dec->output_ = NULL; // leave no trace behind1344}13451346void VP8LDelete(VP8LDecoder* const dec) {1347if (dec != NULL) {1348VP8LClear(dec);1349WebPSafeFree(dec);1350}1351}13521353static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {1354VP8LMetadata* const hdr = &dec->hdr_;1355const int num_bits = hdr->huffman_subsample_bits_;1356dec->width_ = width;1357dec->height_ = height;13581359hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);1360hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;1361}13621363static int DecodeImageStream(int xsize, int ysize,1364int is_level0,1365VP8LDecoder* const dec,1366uint32_t** const decoded_data) {1367int ok = 1;1368int transform_xsize = xsize;1369int transform_ysize = ysize;1370VP8LBitReader* const br = &dec->br_;1371VP8LMetadata* const hdr = &dec->hdr_;1372uint32_t* data = NULL;1373int color_cache_bits = 0;13741375// Read the transforms (may recurse).1376if (is_level0) {1377while (ok && VP8LReadBits(br, 1)) {1378ok = ReadTransform(&transform_xsize, &transform_ysize, dec);1379}1380}13811382// Color cache1383if (ok && VP8LReadBits(br, 1)) {1384color_cache_bits = VP8LReadBits(br, 4);1385ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);1386if (!ok) {1387dec->status_ = VP8_STATUS_BITSTREAM_ERROR;1388goto End;1389}1390}13911392// Read the Huffman codes (may recurse).1393ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,1394color_cache_bits, is_level0);1395if (!ok) {1396dec->status_ = VP8_STATUS_BITSTREAM_ERROR;1397goto End;1398}13991400// Finish setting up the color-cache1401if (color_cache_bits > 0) {1402hdr->color_cache_size_ = 1 << color_cache_bits;1403if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {1404dec->status_ = VP8_STATUS_OUT_OF_MEMORY;1405ok = 0;1406goto End;1407}1408} else {1409hdr->color_cache_size_ = 0;1410}1411UpdateDecoder(dec, transform_xsize, transform_ysize);14121413if (is_level0) { // level 0 complete1414dec->state_ = READ_HDR;1415goto End;1416}14171418{1419const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;1420data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));1421if (data == NULL) {1422dec->status_ = VP8_STATUS_OUT_OF_MEMORY;1423ok = 0;1424goto End;1425}1426}14271428// Use the Huffman trees to decode the LZ77 encoded data.1429ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,1430transform_ysize, NULL);1431ok = ok && !br->eos_;14321433End:1434if (!ok) {1435WebPSafeFree(data);1436ClearMetadata(hdr);1437} else {1438if (decoded_data != NULL) {1439*decoded_data = data;1440} else {1441// We allocate image data in this function only for transforms. At level 01442// (that is: not the transforms), we shouldn't have allocated anything.1443assert(data == NULL);1444assert(is_level0);1445}1446dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.1447if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.1448}1449return ok;1450}14511452//------------------------------------------------------------------------------1453// Allocate internal buffers dec->pixels_ and dec->argb_cache_.1454static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {1455const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;1456// Scratch buffer corresponding to top-prediction row for transforming the1457// first row in the row-blocks. Not needed for paletted alpha.1458const uint64_t cache_top_pixels = (uint16_t)final_width;1459// Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.1460const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;1461const uint64_t total_num_pixels =1462num_pixels + cache_top_pixels + cache_pixels;14631464assert(dec->width_ <= final_width);1465dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));1466if (dec->pixels_ == NULL) {1467dec->argb_cache_ = NULL; // for sanity check1468dec->status_ = VP8_STATUS_OUT_OF_MEMORY;1469return 0;1470}1471dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;1472return 1;1473}14741475static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {1476const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;1477dec->argb_cache_ = NULL; // for sanity check1478dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));1479if (dec->pixels_ == NULL) {1480dec->status_ = VP8_STATUS_OUT_OF_MEMORY;1481return 0;1482}1483return 1;1484}14851486//------------------------------------------------------------------------------14871488// Special row-processing that only stores the alpha data.1489static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {1490int cur_row = dec->last_row_;1491int num_rows = last_row - cur_row;1492const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;14931494assert(last_row <= dec->io_->crop_bottom);1495while (num_rows > 0) {1496const int num_rows_to_process =1497(num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;1498// Extract alpha (which is stored in the green plane).1499ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;1500uint8_t* const output = alph_dec->output_;1501const int width = dec->io_->width; // the final width (!= dec->width_)1502const int cache_pixs = width * num_rows_to_process;1503uint8_t* const dst = output + width * cur_row;1504const uint32_t* const src = dec->argb_cache_;1505ApplyInverseTransforms(dec, num_rows_to_process, in);1506WebPExtractGreen(src, dst, cache_pixs);1507AlphaApplyFilter(alph_dec,1508cur_row, cur_row + num_rows_to_process, dst, width);1509num_rows -= num_rows_to_process;1510in += num_rows_to_process * dec->width_;1511cur_row += num_rows_to_process;1512}1513assert(cur_row == last_row);1514dec->last_row_ = dec->last_out_row_ = last_row;1515}15161517int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,1518const uint8_t* const data, size_t data_size) {1519int ok = 0;1520VP8LDecoder* dec = VP8LNew();15211522if (dec == NULL) return 0;15231524assert(alph_dec != NULL);1525alph_dec->vp8l_dec_ = dec;15261527dec->width_ = alph_dec->width_;1528dec->height_ = alph_dec->height_;1529dec->io_ = &alph_dec->io_;1530dec->io_->opaque = alph_dec;1531dec->io_->width = alph_dec->width_;1532dec->io_->height = alph_dec->height_;15331534dec->status_ = VP8_STATUS_OK;1535VP8LInitBitReader(&dec->br_, data, data_size);15361537if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {1538goto Err;1539}15401541// Special case: if alpha data uses only the color indexing transform and1542// doesn't use color cache (a frequent case), we will use DecodeAlphaData()1543// method that only needs allocation of 1 byte per pixel (alpha channel).1544if (dec->next_transform_ == 1 &&1545dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&1546Is8bOptimizable(&dec->hdr_)) {1547alph_dec->use_8b_decode_ = 1;1548ok = AllocateInternalBuffers8b(dec);1549} else {1550// Allocate internal buffers (note that dec->width_ may have changed here).1551alph_dec->use_8b_decode_ = 0;1552ok = AllocateInternalBuffers32b(dec, alph_dec->width_);1553}15541555if (!ok) goto Err;15561557return 1;15581559Err:1560VP8LDelete(alph_dec->vp8l_dec_);1561alph_dec->vp8l_dec_ = NULL;1562return 0;1563}15641565int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {1566VP8LDecoder* const dec = alph_dec->vp8l_dec_;1567assert(dec != NULL);1568assert(last_row <= dec->height_);15691570if (dec->last_row_ >= last_row) {1571return 1; // done1572}15731574if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing();15751576// Decode (with special row processing).1577return alph_dec->use_8b_decode_ ?1578DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,1579last_row) :1580DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,1581last_row, ExtractAlphaRows);1582}15831584//------------------------------------------------------------------------------15851586int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {1587int width, height, has_alpha;15881589if (dec == NULL) return 0;1590if (io == NULL) {1591dec->status_ = VP8_STATUS_INVALID_PARAM;1592return 0;1593}15941595dec->io_ = io;1596dec->status_ = VP8_STATUS_OK;1597VP8LInitBitReader(&dec->br_, io->data, io->data_size);1598if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {1599dec->status_ = VP8_STATUS_BITSTREAM_ERROR;1600goto Error;1601}1602dec->state_ = READ_DIM;1603io->width = width;1604io->height = height;16051606if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;1607return 1;16081609Error:1610VP8LClear(dec);1611assert(dec->status_ != VP8_STATUS_OK);1612return 0;1613}16141615int VP8LDecodeImage(VP8LDecoder* const dec) {1616VP8Io* io = NULL;1617WebPDecParams* params = NULL;16181619// Sanity checks.1620if (dec == NULL) return 0;16211622assert(dec->hdr_.huffman_tables_ != NULL);1623assert(dec->hdr_.htree_groups_ != NULL);1624assert(dec->hdr_.num_htree_groups_ > 0);16251626io = dec->io_;1627assert(io != NULL);1628params = (WebPDecParams*)io->opaque;1629assert(params != NULL);16301631// Initialization.1632if (dec->state_ != READ_DATA) {1633dec->output_ = params->output;1634assert(dec->output_ != NULL);16351636if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {1637dec->status_ = VP8_STATUS_INVALID_PARAM;1638goto Err;1639}16401641if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;16421643#if !defined(WEBP_REDUCE_SIZE)1644if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;1645#else1646if (io->use_scaling) {1647dec->status_ = VP8_STATUS_INVALID_PARAM;1648goto Err;1649}1650#endif1651if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {1652// need the alpha-multiply functions for premultiplied output or rescaling1653WebPInitAlphaProcessing();1654}16551656if (!WebPIsRGBMode(dec->output_->colorspace)) {1657WebPInitConvertARGBToYUV();1658if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();1659}1660if (dec->incremental_) {1661if (dec->hdr_.color_cache_size_ > 0 &&1662dec->hdr_.saved_color_cache_.colors_ == NULL) {1663if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,1664dec->hdr_.color_cache_.hash_bits_)) {1665dec->status_ = VP8_STATUS_OUT_OF_MEMORY;1666goto Err;1667}1668}1669}1670dec->state_ = READ_DATA;1671}16721673// Decode.1674if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,1675io->crop_bottom, ProcessRows)) {1676goto Err;1677}16781679params->last_y = dec->last_out_row_;1680return 1;16811682Err:1683VP8LClear(dec);1684assert(dec->status_ != VP8_STATUS_OK);1685return 0;1686}16871688//------------------------------------------------------------------------------168916901691