1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved. 2a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license 40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source 50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found 60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may 70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree. 8a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 9a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// main entry for the decoder 11a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 12a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Authors: Vikas Arora (vikaas.arora@gmail.com) 13a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Jyrki Alakuijala (jyrki@google.com) 14a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 15a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <stdlib.h> 16259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi 178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#include "./alphai.h" 18a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8li.h" 1933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../dsp/dsp.h" 20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dsp/lossless.h" 21a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dsp/yuv.h" 22a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../utils/huffman.h" 23a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../utils/utils.h" 24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 25a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define NUM_ARGB_CACHE_ROWS 16 26a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 27a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthLiterals = 16; 28a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthRepeatCode = 16; 29a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; 30a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; 31a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 32a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Five Huffman codes are used at each meta code: 34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 1. green + length prefix codes + color cache codes, 35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 2. alpha, 36a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 3. red, 37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 4. blue, and, 38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 5. distance prefix codes. 39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef enum { 40a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora GREEN = 0, 41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora RED = 1, 42a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora BLUE = 2, 43a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ALPHA = 3, 44a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora DIST = 4 45a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} HuffIndex; 46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = { 48a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora NUM_LITERAL_CODES + NUM_LENGTH_CODES, 49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES, 50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora NUM_DISTANCE_CODES 51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}; 52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define NUM_CODE_LENGTH_CODES 19 55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { 56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}; 58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define CODE_TO_PLANE_CODES 120 608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { 610406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, 620406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, 630406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, 640406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, 650406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, 660406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, 670406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, 680406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, 690406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, 700406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, 710406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, 720406ce1417f76f2034833414dcecc9f56253640cVikas Arora 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}; 74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 75a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int DecodeImageStream(int xsize, int ysize, 76a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int is_level0, 77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec, 78a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t** const decoded_data); 79a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 81a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LCheckSignature(const uint8_t* const data, size_t size) { 838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return (size >= VP8L_FRAME_HEADER_SIZE && 848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora data[0] == VP8L_MAGIC_BYTE && 858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (data[4] >> 5) == 0); // version 86a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 87a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 88a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadImageInfo(VP8LBitReader* const br, 89a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* const width, int* const height, 90a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* const has_alpha) { 918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; 92a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; 93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; 94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *has_alpha = VP8LReadBits(br, 1); 958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; 96a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 97a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 99a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LGetInfo(const uint8_t* data, size_t data_size, 100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* const width, int* const height, int* const has_alpha) { 101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) { 102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; // not enough data 1038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (!VP8LCheckSignature(data, data_size)) { 1048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 0; // bad signature 105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int w, h, a; 107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader br; 108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInitBitReader(&br, data, data_size); 109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ReadImageInfo(&br, &w, &h, &a)) { 110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = w; 113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = h; 114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (has_alpha != NULL) *has_alpha = a; 115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetCopyDistance(int distance_symbol, 122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br) { 123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int extra_bits, offset; 124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (distance_symbol < 4) { 125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return distance_symbol + 1; 126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora extra_bits = (distance_symbol - 2) >> 1; 128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora offset = (2 + (distance_symbol & 1)) << extra_bits; 129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return offset + VP8LReadBits(br, extra_bits) + 1; 130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetCopyLength(int length_symbol, 133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br) { 134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Length and distance prefixes are encoded the same way. 135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return GetCopyDistance(length_symbol, br); 136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { 139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (plane_code > CODE_TO_PLANE_CODES) { 140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return plane_code - CODE_TO_PLANE_CODES; 141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int dist_code = kCodeToPlane[plane_code - 1]; 143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int yoffset = dist_code >> 4; 144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int xoffset = 8 - (dist_code & 0xf); 145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int dist = yoffset * xsize + xoffset; 1468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small 147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Decodes the next Huffman code from bit-stream. 152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// FillBitWindow(br) needs to be called at minimum every second call 1531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// to ReadSymbol, in order to pre-fetch enough bits. 1541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int ReadSymbol(const HuffmanTree* tree, 1551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8LBitReader* const br) { 156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const HuffmanTreeNode* node = tree->root_; 1571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora uint32_t bits = VP8LPrefetchBits(br); 1588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int bitpos = br->bit_pos_; 1598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Check if we find the bit combination from the Huffman lookup table. 1608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int lut_ix = bits & (HUFF_LUT - 1); 1618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int lut_bits = tree->lut_bits_[lut_ix]; 1628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (lut_bits <= HUFF_LUT_BITS) { 1638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LSetBitPos(br, bitpos + lut_bits); 1648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return tree->lut_symbol_[lut_ix]; 1658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora node += tree->lut_jump_[lut_ix]; 1678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora bitpos += HUFF_LUT_BITS; 1688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora bits >>= HUFF_LUT_BITS; 1698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Decode the value from a binary tree. 171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(node != NULL); 1728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora do { 1731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora node = HuffmanTreeNextNode(node, bits & 1); 1741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora bits >>= 1; 1758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++bitpos; 1768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } while (HuffmanTreeNodeIsNotLeaf(node)); 1778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LSetBitPos(br, bitpos); 178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return node->symbol_; 179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCodeLengths( 182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec, const int* const code_length_code_lengths, 183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_symbols, int* const code_lengths) { 184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 0; 185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 186a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int symbol; 187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int max_symbol; 188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int prev_code_len = DEFAULT_CODE_LENGTH; 189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HuffmanTree tree; 19033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int huff_codes[NUM_CODE_LENGTH_CODES] = { 0 }; 191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 19233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!VP8LHuffmanTreeBuildImplicit(&tree, code_length_code_lengths, 19333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora huff_codes, NUM_CODE_LENGTH_CODES)) { 194a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 195a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 197a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 198a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (VP8LReadBits(br, 1)) { // use length 199a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int length_nbits = 2 + 2 * VP8LReadBits(br, 3); 200a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora max_symbol = 2 + VP8LReadBits(br, length_nbits); 201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (max_symbol > num_symbols) { 202a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 203a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 205a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 206a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora max_symbol = num_symbols; 207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 208a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 209a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora symbol = 0; 210a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (symbol < num_symbols) { 211a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int code_len; 212a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (max_symbol-- == 0) break; 213a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LFillBitWindow(br); 214a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_len = ReadSymbol(&tree, br); 215a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (code_len < kCodeLengthLiterals) { 216a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths[symbol++] = code_len; 217a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (code_len != 0) prev_code_len = code_len; 218a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 219a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int use_prev = (code_len == kCodeLengthRepeatCode); 220a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int slot = code_len - kCodeLengthLiterals; 221a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int extra_bits = kCodeLengthExtraBits[slot]; 222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int repeat_offset = kCodeLengthRepeatOffsets[slot]; 223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int repeat = VP8LReadBits(br, extra_bits) + repeat_offset; 224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (symbol + repeat > num_symbols) { 225a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 228a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int length = use_prev ? prev_code_len : 0; 229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (repeat-- > 0) code_lengths[symbol++] = length; 230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = 1; 234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora End: 23633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora VP8LHuffmanTreeFree(&tree); 2378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ok; 239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 24133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman 24233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// tree. 243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, 24433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int* const code_lengths, int* const huff_codes, 245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HuffmanTree* const tree) { 246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 0; 247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int simple_code = VP8LReadBits(br, 1); 249a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 250a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (simple_code) { // Read symbols, codes & code lengths directly. 251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int symbols[2]; 252a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int codes[2]; 253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_symbols = VP8LReadBits(br, 1) + 1; 254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int first_symbol_len_code = VP8LReadBits(br, 1); 255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // The first code is either 1 bit or 8 bit code. 256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); 257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora codes[0] = 0; 258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths[0] = num_symbols - 1; 259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // The second code (if present), is always 8 bit long. 260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_symbols == 2) { 261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora symbols[1] = VP8LReadBits(br, 8); 262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora codes[1] = 1; 263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths[1] = num_symbols - 1; 264a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 26533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora ok = VP8LHuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols, 26633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora alphabet_size, num_symbols); 267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // Decode Huffman-coded code lengths. 268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; 270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_codes = VP8LReadBits(br, 4) + 4; 271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_codes > NUM_CODE_LENGTH_CODES) { 272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 275a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 27633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); 277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < num_codes; ++i) { 279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); 280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size, 282a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths); 28333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora ok = ok && VP8LHuffmanTreeBuildImplicit(tree, code_lengths, huff_codes, 28433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora alphabet_size); 285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && !br->error_; 287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, 295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int color_cache_bits, int allow_recursion) { 296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i, j; 297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 298a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LMetadata* const hdr = &dec->hdr_; 299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* huffman_image = NULL; 300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HTreeGroup* htree_groups = NULL; 301a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_htree_groups = 1; 30233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int max_alphabet_size = 0; 30333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int* code_lengths = NULL; 30433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int* huff_codes = NULL; 305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (allow_recursion && VP8LReadBits(br, 1)) { 307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // use meta Huffman codes. 308a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_precision = VP8LReadBits(br, 3) + 2; 309a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); 310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); 311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_pixs = huffman_xsize * huffman_ysize; 312a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, 313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora &huffman_image)) { 314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 315a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Error; 316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_subsample_bits_ = huffman_precision; 318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < huffman_pixs; ++i) { 319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // The huffman data is stored in red and green bytes. 3201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int group = (huffman_image[i] >> 8) & 0xffff; 3211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora huffman_image[i] = group; 3221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (group >= num_htree_groups) { 3231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora num_htree_groups = group + 1; 324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (br->error_) goto Error; 329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 33033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // Find maximum alphabet size for the htree group. 33133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { 33233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int alphabet_size = kAlphabetSize[j]; 33333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (j == 0 && color_cache_bits > 0) { 33433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora alphabet_size += 1 << color_cache_bits; 33533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 33633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (max_alphabet_size < alphabet_size) { 33733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora max_alphabet_size = alphabet_size; 33833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 33933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 34033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 34133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora htree_groups = VP8LHtreeGroupsNew(num_htree_groups); 34233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora code_lengths = 34333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); 34433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora huff_codes = 34533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora (int*)WebPSafeMalloc((uint64_t)max_alphabet_size, sizeof(*huff_codes)); 34633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 34733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (htree_groups == NULL || code_lengths == NULL || huff_codes == NULL) { 348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Error; 350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < num_htree_groups; ++i) { 353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HuffmanTree* const htrees = htree_groups[i].htrees_; 354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { 355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int alphabet_size = kAlphabetSize[j]; 35633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora HuffmanTree* const htree = htrees + j; 357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (j == 0 && color_cache_bits > 0) { 358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora alphabet_size += 1 << color_cache_bits; 359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 36033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, huff_codes, 36133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora htree)) { 36233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora goto Error; 36333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 36633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(huff_codes); 36733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(code_lengths); 368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // All OK. Finalize pointers and return. 370a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_image_ = huffman_image; 371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->num_htree_groups_ = num_htree_groups; 372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->htree_groups_ = htree_groups; 373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 375a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error: 37633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(huff_codes); 37733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(code_lengths); 37833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(huffman_image); 37933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora VP8LHtreeGroupsFree(htree_groups, num_htree_groups); 380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 381a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 382a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Scaling. 385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { 387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_channels = 4; 388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int in_width = io->mb_w; 389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int out_width = io->scaled_width; 390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int in_height = io->mb_h; 391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int out_height = io->scaled_height; 392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t work_size = 2 * num_channels * (uint64_t)out_width; 393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int32_t* work; // Rescaler work area. 394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t scaled_data_size = num_channels * (uint64_t)out_width; 395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* scaled_data; // Temporary storage for scaled BGRA data. 396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t memory_size = sizeof(*dec->rescaler) + 397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora work_size * sizeof(*work) + 398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora scaled_data_size * sizeof(*scaled_data); 399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory)); 400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (memory == NULL) { 401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->rescaler_memory == NULL); 405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->rescaler_memory = memory; 406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->rescaler = (WebPRescaler*)memory; 408a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memory += sizeof(*dec->rescaler); 409a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora work = (int32_t*)memory; 410a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memory += work_size * sizeof(*work); 411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora scaled_data = (uint32_t*)memory; 412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data, 414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora out_width, out_height, 0, num_channels, 415a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora in_width, out_width, in_height, out_height, work); 416a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 418a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to ARGB 421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// We have special "export" function since we need to convert from BGRA 423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, 424a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int rgba_stride, uint8_t* const rgba) { 4258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src = (uint32_t*)rescaler->dst; 426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int dst_width = rescaler->dst_width; 427a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_out = 0; 428a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (WebPRescalerHasPendingOutput(rescaler)) { 429a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const dst = rgba + num_lines_out * rgba_stride; 43033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPRescalerExportRow(rescaler, 0); 4318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRow(src, dst_width, 1); 432a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LConvertFromBGRA(src, dst_width, colorspace, dst); 433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++num_lines_out; 434a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return num_lines_out; 436a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 438a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit scaled rows. 4398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, 4408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* in, int in_stride, int mb_h, 4418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const out, int out_stride) { 442a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WEBP_CSP_MODE colorspace = dec->output_->colorspace; 443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_in = 0; 444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_out = 0; 445a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (num_lines_in < mb_h) { 4468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const row_in = in + num_lines_in * in_stride; 447a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const row_out = out + num_lines_out * out_stride; 4488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int lines_left = mb_h - num_lines_in; 4498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); 4508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(needed_lines > 0 && needed_lines <= lines_left); 4518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRows(row_in, in_stride, 4528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->rescaler->src_width, needed_lines, 0); 4538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); 4548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora num_lines_in += needed_lines; 455a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); 456a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 457a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return num_lines_out; 458a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 459a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 460a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit rows without any scaling. 461a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRows(WEBP_CSP_MODE colorspace, 4628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* row_in, int in_stride, 463a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int mb_w, int mb_h, 464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const out, int out_stride) { 465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int lines = mb_h; 466a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* row_out = out; 467a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (lines-- > 0) { 468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); 469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora row_in += in_stride; 470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora row_out += out_stride; 471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return mb_h; // Num rows out == num rows in. 473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to YUVA 477a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 47833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// TODO(skal): should be in yuv.c 479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, 480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPDecBuffer* const output) { 481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPYUVABuffer* const buf = &output->u.YUVA; 482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // first, the luma plane 483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const y = buf->y + y_pos * buf->y_stride; 486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < width; ++i) { 487a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t p = src[i]; 4888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, 4898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora YUV_HALF); 490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // then U/V planes 494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; 496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; 497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int uv_width = width >> 1; 498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < uv_width; ++i) { 500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t v0 = src[2 * i + 0]; 501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t v1 = src[2 * i + 1]; 502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // VP8RGBToU/V expects four accumulated pixels. Hence we need to 503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. 504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); 505a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); 506a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); 507a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!(y_pos & 1)) { // even lines: store values 5088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); 5098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); 510a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // odd lines: average with previous values 5118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); 5128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); 513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Approximated average-of-four. But it's an acceptable diff. 514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u[i] = (u[i] + tmp_u + 1) >> 1; 515a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v[i] = (v[i] + tmp_v + 1) >> 1; 516a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width & 1) { // last pixel 519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t v0 = src[2 * i + 0]; 520a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int r = (v0 >> 14) & 0x3fc; 521a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int g = (v0 >> 6) & 0x3fc; 522a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int b = (v0 << 2) & 0x3fc; 523a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!(y_pos & 1)) { // even lines 5248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); 5258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); 526a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // odd lines (note: we could just skip this) 5278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); 5288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); 529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u[i] = (u[i] + tmp_u + 1) >> 1; 530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v[i] = (v[i] + tmp_v + 1) >> 1; 531a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 532a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 533a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 534a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Lastly, store alpha if needed. 535a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (buf->a != NULL) { 536a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 537a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const a = buf->a + y_pos * buf->a_stride; 538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < width; ++i) a[i] = (src[i] >> 24); 539a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 540a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 541a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 542a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { 543a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPRescaler* const rescaler = dec->rescaler; 5448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src = (uint32_t*)rescaler->dst; 545a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int dst_width = rescaler->dst_width; 546a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_out = 0; 547a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (WebPRescalerHasPendingOutput(rescaler)) { 54833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPRescalerExportRow(rescaler, 0); 5498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRow(src, dst_width, 1); 550a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ConvertToYUVA(src, dst_width, y_pos, dec->output_); 551a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++y_pos; 552a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++num_lines_out; 553a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 554a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return num_lines_out; 555a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 556a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 557a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, 5588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* in, int in_stride, int mb_h) { 559a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_in = 0; 560a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int y_pos = dec->last_out_row_; 561a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (num_lines_in < mb_h) { 5628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int lines_left = mb_h - num_lines_in; 5638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); 5648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); 5658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); 5668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora num_lines_in += needed_lines; 5678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora in += needed_lines * in_stride; 568a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora y_pos += ExportYUVA(dec, y_pos); 569a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 570a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return y_pos; 571a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 572a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 573a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRowsYUVA(const VP8LDecoder* const dec, 5748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* in, int in_stride, 575a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int mb_w, int num_rows) { 576a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int y_pos = dec->last_out_row_; 577a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (num_rows-- > 0) { 5788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_); 5798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora in += in_stride; 580a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++y_pos; 581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return y_pos; 583a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Cropping. 587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 588a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and 589a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// crop options. Also updates the input data pointer, so that it points to the 5908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// start of the cropped window. Note that pixels are in ARGB format even if 5918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 'in_data' is uint8_t*. 592a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Returns true if the crop window is not empty. 593a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int SetCropWindow(VP8Io* const io, int y_start, int y_end, 5948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t** const in_data, int pixel_stride) { 595a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(y_start < y_end); 596a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(io->crop_left < io->crop_right); 597a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (y_end > io->crop_bottom) { 598a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora y_end = io->crop_bottom; // make sure we don't overflow on last row. 599a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 600a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (y_start < io->crop_top) { 601a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int delta = io->crop_top - y_start; 602a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora y_start = io->crop_top; 6038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora *in_data += delta * pixel_stride; 604a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 605a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (y_start >= y_end) return 0; // Crop window is empty. 606a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 6078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora *in_data += io->crop_left * sizeof(uint32_t); 608a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 609a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_y = y_start - io->crop_top; 610a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_w = io->crop_right - io->crop_left; 611a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_h = y_end - y_start; 612a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; // Non-empty crop window. 613a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 614a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 615a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 616a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 617a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetMetaIndex( 618a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* const image, int xsize, int bits, int x, int y) { 619a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (bits == 0) return 0; 620a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return image[xsize * (y >> bits) + (x >> bits)]; 621a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 622a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 623a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, 624a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int x, int y) { 625a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_, 626a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_subsample_bits_, x, y); 627a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(meta_index < hdr->num_htree_groups_); 628a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return hdr->htree_groups_ + meta_index; 629a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 631a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 632a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Main loop, with custom row-processing function 633a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 634a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); 635a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, 637a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* const rows) { 638a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int n = dec->next_transform_; 639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int cache_pixs = dec->width_ * num_rows; 640a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int start_row = dec->last_row_; 641a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int end_row = start_row + num_rows; 642a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* rows_in = rows; 643a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* const rows_out = dec->argb_cache_; 644a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 645a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Inverse transforms. 646a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // TODO: most transforms only need to operate on the cropped region only. 647a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); 648a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (n-- > 0) { 649a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LTransform* const transform = &dec->transforms_[n]; 650a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); 651a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rows_in = rows_out; 652a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 653a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 654a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 6550406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special method for paletted alpha data. 6560406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, 6570406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t* const rows) { 6580406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int start_row = dec->last_row_; 6590406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int end_row = start_row + num_rows; 6600406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t* rows_in = rows; 6610406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; 6620406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8LTransform* const transform = &dec->transforms_[0]; 6630406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(dec->next_transform_ == 1); 6640406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(transform->type_ == COLOR_INDEXING_TRANSFORM); 6650406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in, 6660406ce1417f76f2034833414dcecc9f56253640cVikas Arora rows_out); 6670406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 6680406ce1417f76f2034833414dcecc9f56253640cVikas Arora 669a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Processes (transforms, scales & color-converts) the rows decoded after the 670a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// last call. 671a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ProcessRows(VP8LDecoder* const dec, int row) { 6720406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; 673a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_rows = row - dec->last_row_; 674a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 675a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_rows <= 0) return; // Nothing to be done. 676a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ApplyInverseTransforms(dec, num_rows, rows); 677a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 678a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Emit output. 679a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 680a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Io* const io = dec->io_; 6818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* rows_data = (uint8_t*)dec->argb_cache_; 6828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA 6838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { 684a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Nothing to output (this time). 685a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 686a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPDecBuffer* const output = dec->output_; 687a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (output->colorspace < MODE_YUV) { // convert to RGBA 688a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPRGBABuffer* const buf = &output->u.RGBA; 689a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; 690a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_rows_out = io->use_scaling ? 6918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, 6928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora rgba, buf->stride) : 693a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora EmitRows(output->colorspace, rows_data, in_stride, 694a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_w, io->mb_h, rgba, buf->stride); 695a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Update 'last_out_row_'. 696a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->last_out_row_ += num_rows_out; 697a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // convert to YUVA 698a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->last_out_row_ = io->use_scaling ? 699a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : 700a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); 701a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 702a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->last_out_row_ <= output->height); 703a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 704a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 705a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 706a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Update 'last_row_'. 707a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->last_row_ = row; 708a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->last_row_ <= dec->height_); 709a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 710a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 7118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Row-processing for the special case when alpha data contains only one 7128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// transform (color indexing), and trivial non-green literals. 7138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int Is8bOptimizable(const VP8LMetadata* const hdr) { 7148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int i; 7158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (hdr->color_cache_size_ > 0) return 0; 7168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // When the Huffman tree contains only one symbol, we can skip the 7178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // call to ReadSymbol() for red/blue/alpha channels. 7188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (i = 0; i < hdr->num_htree_groups_; ++i) { 7198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_; 7208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (htrees[RED].num_nodes_ > 1) return 0; 7218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (htrees[BLUE].num_nodes_ > 1) return 0; 7228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (htrees[ALPHA].num_nodes_ > 1) return 0; 7238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 7250406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 726a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 7278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { 7288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int num_rows = row - dec->last_row_; 7298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* const in = 7308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; 7318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (num_rows > 0) { 7328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ApplyInverseTransformsAlpha(dec, num_rows, in); 7338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_row_ = dec->last_out_row_ = row; 7350406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 736a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 7378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, 7388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int width, int height, int last_row) { 7398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int ok = 1; 7408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int row = dec->last_pixel_ / width; 7418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int col = dec->last_pixel_ % width; 7428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LBitReader* const br = &dec->br_; 7438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LMetadata* const hdr = &dec->hdr_; 7448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); 7458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int pos = dec->last_pixel_; // current position 7468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int end = width * height; // End of data 7478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int last = width * last_row; // Last pixel to decode 7488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; 7498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int mask = hdr->huffman_mask_; 7508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(htree_group != NULL); 751259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi assert(pos < end); 7528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(last_row <= height); 7538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(Is8bOptimizable(hdr)); 7548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 7558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (!br->eos_ && pos < last) { 7568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int code; 7578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Only update when changing tile. 7588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((col & mask) == 0) { 7598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora htree_group = GetHtreeGroupForPos(hdr, col, row); 7608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 7628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora code = ReadSymbol(&htree_group->htrees_[GREEN], br); 7638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (code < NUM_LITERAL_CODES) { // Literal 7648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora data[pos] = code; 7658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++pos; 7668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++col; 7678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (col >= width) { 7688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col = 0; 7698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 7708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (row % NUM_ARGB_CACHE_ROWS == 0) { 7718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ExtractPalettedAlphaRows(dec, row); 7728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (code < len_code_limit) { // Backward reference 7758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int dist_code, dist; 7768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length_sym = code - NUM_LITERAL_CODES; 7778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length = GetCopyLength(length_sym, br); 7788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); 7798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 7808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist_code = GetCopyDistance(dist_symbol, br); 7818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist = PlaneCodeToDistance(width, dist_code); 7828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (pos >= dist && end - pos >= length) { 7838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int i; 7848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist]; 7858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 7868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 7878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 7888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora pos += length; 7908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col += length; 7918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (col >= width) { 7928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col -= width; 7938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 7948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (row % NUM_ARGB_CACHE_ROWS == 0) { 7958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ExtractPalettedAlphaRows(dec, row); 7968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (pos < last && (col & mask)) { 7998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora htree_group = GetHtreeGroupForPos(hdr, col, row); 8008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { // Not reached 8028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 8038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 8048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(br->eos_ == VP8LIsEndOfStream(br)); 8068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = !br->error_; 8078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) goto End; 8088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Process the remaining rows corresponding to last row-block. 8108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ExtractPalettedAlphaRows(dec, row); 8118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 8128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End: 8138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (br->error_ || !ok || (br->eos_ && pos < end)) { 8148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 8158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED 8168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora : VP8_STATUS_BITSTREAM_ERROR; 8178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 8188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_pixel_ = (int)pos; 8198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (pos == end) dec->state_ = READ_DATA; 8208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return ok; 822a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 823a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 8248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, 8258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int width, int height, int last_row, 8268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ProcessRowsFunc process_func) { 8278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int ok = 1; 8288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int row = dec->last_pixel_ / width; 8298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int col = dec->last_pixel_ % width; 8308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LBitReader* const br = &dec->br_; 8318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LMetadata* const hdr = &dec->hdr_; 8328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); 8338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* src = data + dec->last_pixel_; 8348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* last_cached = src; 8358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src_end = data + width * height; // End of data 8368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src_last = data + width * last_row; // Last pixel to decode 8378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; 8388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int color_cache_limit = len_code_limit + hdr->color_cache_size_; 8398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCache* const color_cache = 8408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; 8418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int mask = hdr->huffman_mask_; 8428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(htree_group != NULL); 843259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi assert(src < src_end); 8448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(src_last <= src_end); 8458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 8468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (!br->eos_ && src < src_last) { 8478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int code; 8488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Only update when changing tile. Note we could use this test: 8498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed 8508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // but that's actually slower and needs storing the previous col/row. 8518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((col & mask) == 0) { 8528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora htree_group = GetHtreeGroupForPos(hdr, col, row); 8538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 8558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora code = ReadSymbol(&htree_group->htrees_[GREEN], br); 8568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (code < NUM_LITERAL_CODES) { // Literal 8578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int red, green, blue, alpha; 8588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora red = ReadSymbol(&htree_group->htrees_[RED], br); 8598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora green = code; 8608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 8618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora blue = ReadSymbol(&htree_group->htrees_[BLUE], br); 8628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br); 86333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora *src = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | blue; 8648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora AdvanceByOne: 8658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++src; 8668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++col; 8678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (col >= width) { 8688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col = 0; 8698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 8708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { 8718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora process_func(dec, row); 8728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (color_cache != NULL) { 8748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (last_cached < src) { 8758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCacheInsert(color_cache, *last_cached++); 8768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (code < len_code_limit) { // Backward reference 8808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int dist_code, dist; 8818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length_sym = code - NUM_LITERAL_CODES; 8828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length = GetCopyLength(length_sym, br); 8838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); 8848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 8858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist_code = GetCopyDistance(dist_symbol, br); 8868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist = PlaneCodeToDistance(width, dist_code); 8878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { 8888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 8898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 8908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 8918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int i; 8928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (i = 0; i < length; ++i) src[i] = src[i - dist]; 8938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora src += length; 8948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col += length; 8968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (col >= width) { 8978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col -= width; 8988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 8998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { 9008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora process_func(dec, row); 9018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (src < src_end) { 9048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); 9058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (color_cache != NULL) { 9068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (last_cached < src) { 9078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCacheInsert(color_cache, *last_cached++); 9088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (code < color_cache_limit) { // Color cache 9128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int key = code - len_code_limit; 9138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(color_cache != NULL); 9148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (last_cached < src) { 9158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCacheInsert(color_cache, *last_cached++); 9168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora *src = VP8LColorCacheLookup(color_cache, key); 9188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto AdvanceByOne; 9198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { // Not reached 9208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 9218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 9228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(br->eos_ == VP8LIsEndOfStream(br)); 9248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = !br->error_; 9258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) goto End; 9268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Process the remaining rows corresponding to last row-block. 9288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (process_func != NULL) process_func(dec, row); 9290406ce1417f76f2034833414dcecc9f56253640cVikas Arora 9308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End: 9318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (br->error_ || !ok || (br->eos_ && src < src_end)) { 9328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 9338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED 9348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora : VP8_STATUS_BITSTREAM_ERROR; 9358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 9368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_pixel_ = (int)(src - data); 9378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (src == src_end) dec->state_ = READ_DATA; 9388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return ok; 9408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 9410406ce1417f76f2034833414dcecc9f56253640cVikas Arora 942a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 943a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LTransform 944a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 945a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearTransform(VP8LTransform* const transform) { 94633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(transform->data_); 947a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->data_ = NULL; 948a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 949a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 950a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// For security reason, we need to remap the color map to span 951a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// the total possible bundled values, and not just the num_colors. 952a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExpandColorMap(int num_colors, VP8LTransform* const transform) { 953a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 954a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int final_num_colors = 1 << (8 >> transform->bits_); 955a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* const new_color_map = 956a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, 957a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora sizeof(*new_color_map)); 958a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (new_color_map == NULL) { 959a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 960a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 961a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const data = (uint8_t*)transform->data_; 962a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const new_data = (uint8_t*)new_color_map; 963a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora new_color_map[0] = transform->data_[0]; 964a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 4; i < 4 * num_colors; ++i) { 965a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Equivalent to AddPixelEq(), on a byte-basis. 966a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora new_data[i] = (data[i] + new_data[i - 4]) & 0xff; 967a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 968a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (; i < 4 * final_num_colors; ++i) 969a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora new_data[i] = 0; // black tail. 97033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(transform->data_); 971a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->data_ = new_color_map; 972a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 973a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 974a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 975a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 976a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadTransform(int* const xsize, int const* ysize, 977a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec) { 978a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 1; 979a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 980a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LTransform* transform = &dec->transforms_[dec->next_transform_]; 981a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const VP8LImageTransformType type = 982a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (VP8LImageTransformType)VP8LReadBits(br, 2); 983a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 984a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Each transform type can only be present once in the stream. 985a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec->transforms_seen_ & (1U << type)) { 986a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; // Already there, let's not accept the second same transform. 987a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 988a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->transforms_seen_ |= (1U << type); 989a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 990a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->type_ = type; 991a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->xsize_ = *xsize; 992a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->ysize_ = *ysize; 993a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->data_ = NULL; 994a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++dec->next_transform_; 995a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->next_transform_ <= NUM_TRANSFORMS); 996a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 997a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora switch (type) { 998a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case PREDICTOR_TRANSFORM: 999a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case CROSS_COLOR_TRANSFORM: 1000a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_ = VP8LReadBits(br, 3) + 2; 1001a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_, 1002a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_), 1003a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LSubSampleSize(transform->ysize_, 1004a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_), 1005a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 0, dec, &transform->data_); 1006a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1007a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case COLOR_INDEXING_TRANSFORM: { 1008a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_colors = VP8LReadBits(br, 8) + 1; 1009a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int bits = (num_colors > 16) ? 0 1010a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora : (num_colors > 4) ? 1 1011a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora : (num_colors > 2) ? 2 1012a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora : 3; 1013a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *xsize = VP8LSubSampleSize(transform->xsize_, bits); 1014a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_ = bits; 1015a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_); 1016a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && ExpandColorMap(num_colors, transform); 1017a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1018a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1019a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case SUBTRACT_GREEN: 1020a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1021a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora default: 1022a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(0); // can't happen 1023a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1024a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1025a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1026a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ok; 1027a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1028a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1029a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 1030a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LMetadata 1031a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1032a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void InitMetadata(VP8LMetadata* const hdr) { 1033a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(hdr); 1034a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memset(hdr, 0, sizeof(*hdr)); 1035a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1036a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1037a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearMetadata(VP8LMetadata* const hdr) { 1038a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(hdr); 1039a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 104033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(hdr->huffman_image_); 104133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora VP8LHtreeGroupsFree(hdr->htree_groups_, hdr->num_htree_groups_); 1042a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LColorCacheClear(&hdr->color_cache_); 1043a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora InitMetadata(hdr); 1044a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1045a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1046a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 1047a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LDecoder 1048a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1049a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8LDecoder* VP8LNew(void) { 105033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); 1051a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return NULL; 1052a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OK; 1053a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_DIM; 1054a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->state_ = READ_DIM; 10558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 10568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDspInit(); // Init critical function pointers. 10578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1058a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return dec; 1059a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1060a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1061a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LClear(VP8LDecoder* const dec) { 1062a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 1063a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return; 1064a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ClearMetadata(&dec->hdr_); 1065a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 106633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(dec->pixels_); 10670406ce1417f76f2034833414dcecc9f56253640cVikas Arora dec->pixels_ = NULL; 1068a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < dec->next_transform_; ++i) { 1069a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ClearTransform(&dec->transforms_[i]); 1070a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1071a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->next_transform_ = 0; 1072a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->transforms_seen_ = 0; 1073a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 107433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(dec->rescaler_memory); 1075a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->rescaler_memory = NULL; 1076a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1077a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->output_ = NULL; // leave no trace behind 1078a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1079a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1080a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LDelete(VP8LDecoder* const dec) { 1081a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec != NULL) { 1082a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LClear(dec); 108333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(dec); 1084a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1085a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1086a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1087a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void UpdateDecoder(VP8LDecoder* const dec, int width, int height) { 1088a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LMetadata* const hdr = &dec->hdr_; 1089a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_bits = hdr->huffman_subsample_bits_; 1090a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->width_ = width; 1091a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->height_ = height; 1092a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1093a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits); 1094a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1; 1095a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1096a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1097a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int DecodeImageStream(int xsize, int ysize, 1098a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int is_level0, 1099a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec, 1100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t** const decoded_data) { 1101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 1; 1102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int transform_xsize = xsize; 1103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int transform_ysize = ysize; 1104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 1105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LMetadata* const hdr = &dec->hdr_; 1106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* data = NULL; 1107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int color_cache_bits = 0; 1108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Read the transforms (may recurse). 1110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (is_level0) { 1111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (ok && VP8LReadBits(br, 1)) { 1112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ReadTransform(&transform_xsize, &transform_ysize, dec); 1113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Color cache 1117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (ok && VP8LReadBits(br, 1)) { 1118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora color_cache_bits = VP8LReadBits(br, 4); 1119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); 1120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 1121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 1122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Read the Huffman codes (may recurse). 1127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, 1128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora color_cache_bits, is_level0); 1129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 1130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 1131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Finish setting up the color-cache 1135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (color_cache_bits > 0) { 1136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->color_cache_size_ = 1 << color_cache_bits; 1137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { 1138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = 0; 1140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->color_cache_size_ = 0; 1144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora UpdateDecoder(dec, transform_xsize, transform_ysize); 1146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (is_level0) { // level 0 complete 1148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->state_ = READ_HDR; 1149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 1153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; 1154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); 1155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (data == NULL) { 1156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = 0; 1158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1159a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1160a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1161a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Use the Huffman trees to decode the LZ77 encoded data. 11638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, 11648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora transform_ysize, NULL); 1165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && !br->error_; 1166a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1167a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora End: 1168a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 117033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPSafeFree(data); 1171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ClearMetadata(hdr); 1172a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the 1173a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // status appropriately. 1174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) { 1175a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_SUSPENDED; 1176a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1177a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (decoded_data != NULL) { 1179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *decoded_data = data; 1180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // We allocate image data in this function only for transforms. At level 0 1182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // (that is: not the transforms), we shouldn't have allocated anything. 1183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(data == NULL); 1184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(is_level0); 1185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 11868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls. 1187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. 1188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ok; 1190a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 11930406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Allocate internal buffers dec->pixels_ and dec->argb_cache_. 11948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { 1195a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; 1196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Scratch buffer corresponding to top-prediction row for transforming the 11970406ce1417f76f2034833414dcecc9f56253640cVikas Arora // first row in the row-blocks. Not needed for paletted alpha. 11988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t cache_top_pixels = (uint16_t)final_width; 11990406ce1417f76f2034833414dcecc9f56253640cVikas Arora // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. 12008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; 1201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t total_num_pixels = 1202a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora num_pixels + cache_top_pixels + cache_pixels; 1203a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->width_ <= final_width); 12058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); 12060406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (dec->pixels_ == NULL) { 1207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->argb_cache_ = NULL; // for sanity check 1208a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1209a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 1210a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 12118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; 12128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 12138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 12148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 12158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers8b(VP8LDecoder* const dec) { 12168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_; 12178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->argb_cache_ = NULL; // for sanity check 12188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); 12198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (dec->pixels_ == NULL) { 12208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 12218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 0; 12228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 1224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1225a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12280406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special row-processing that only stores the alpha data. 1229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ExtractAlphaRows(VP8LDecoder* const dec, int row) { 1230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_rows = row - dec->last_row_; 12310406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; 1232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_rows <= 0) return; // Nothing to be done. 1234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ApplyInverseTransforms(dec, num_rows, in); 1235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1236a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Extract alpha (which is stored in the green plane). 1237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 1238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int width = dec->io_->width; // the final width (!= dec->width_) 1239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int cache_pixs = width * num_rows; 1240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; 1241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* const src = dec->argb_cache_; 1242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 1243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; 1244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 12450406ce1417f76f2034833414dcecc9f56253640cVikas Arora dec->last_row_ = dec->last_out_row_ = row; 12460406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12488b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, 12498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* const data, size_t data_size, 12508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const output) { 1251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 0; 12528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDecoder* dec; 12538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8Io* io; 12548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(alph_dec != NULL); 12558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->vp8l_dec_ = VP8LNew(); 12568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (alph_dec->vp8l_dec_ == NULL) return 0; 12578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec = alph_dec->vp8l_dec_; 12588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 12598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->width_ = alph_dec->width_; 12608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->height_ = alph_dec->height_; 12618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->io_ = &alph_dec->io_; 12628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io = dec->io_; 1263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8InitIo(io); 12658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used. 12668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io->opaque = output; 12678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io->width = alph_dec->width_; 12688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io->height = alph_dec->height_; 1269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OK; 1271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInitBitReader(&dec->br_, data, data_size); 1272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_HDR; 12748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { 12758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto Err; 12768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12780406ce1417f76f2034833414dcecc9f56253640cVikas Arora // Special case: if alpha data uses only the color indexing transform and 12790406ce1417f76f2034833414dcecc9f56253640cVikas Arora // doesn't use color cache (a frequent case), we will use DecodeAlphaData() 12800406ce1417f76f2034833414dcecc9f56253640cVikas Arora // method that only needs allocation of 1 byte per pixel (alpha channel). 12810406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (dec->next_transform_ == 1 && 12820406ce1417f76f2034833414dcecc9f56253640cVikas Arora dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && 12838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora Is8bOptimizable(&dec->hdr_)) { 12848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->use_8b_decode = 1; 12858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = AllocateInternalBuffers8b(dec); 12868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 12878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Allocate internal buffers (note that dec->width_ may have changed here). 12888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->use_8b_decode = 0; 12898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = AllocateInternalBuffers32b(dec, alph_dec->width_); 12900406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 12910406ce1417f76f2034833414dcecc9f56253640cVikas Arora 12928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) goto Err; 1293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_DATA; 12958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 1296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err: 12988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDelete(alph_dec->vp8l_dec_); 12998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->vp8l_dec_ = NULL; 13008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 0; 13018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 13028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 13038b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { 13048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDecoder* const dec = alph_dec->vp8l_dec_; 13058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec != NULL); 13068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec->action_ == READ_DATA); 13078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(last_row <= dec->height_); 13088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1309259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi if (dec->last_pixel_ == dec->width_ * dec->height_) { 1310259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi return 1; // done 1311259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi } 1312259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi 13138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Decode (with special row processing). 13148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return alph_dec->use_8b_decode ? 13158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, 13168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora last_row) : 13178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, 13188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora last_row, ExtractAlphaRows); 1319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1320a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1321a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { 1324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int width, height, has_alpha; 1325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return 0; 1327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (io == NULL) { 1328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_INVALID_PARAM; 1329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 1330a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1331a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1332a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->io_ = io; 1333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OK; 1334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInitBitReader(&dec->br_, io->data, io->data_size); 1335a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { 1336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 1337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Error; 1338a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->state_ = READ_DIM; 1340a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->width = width; 1341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->height = height; 1342a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1343a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_HDR; 1344a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error; 1345a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 1346a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error: 13480406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8LClear(dec); 13490406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(dec->status_ != VP8_STATUS_OK); 13500406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 1351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeImage(VP8LDecoder* const dec) { 1354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Io* io = NULL; 1355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPDecParams* params = NULL; 1356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Sanity checks. 1358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return 0; 1359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 13608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 13618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(dec->hdr_.htree_groups_ != NULL); 13628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(dec->hdr_.num_htree_groups_ > 0); 13638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io = dec->io_; 1365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(io != NULL); 1366a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora params = (WebPDecParams*)io->opaque; 1367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(params != NULL); 1368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->output_ = params->output; 1369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->output_ != NULL); 1370a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Initialization. 1372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { 1373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_INVALID_PARAM; 1374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Err; 1375a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1376a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 13778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; 1378a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1379a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; 1380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 138133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { 138233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // need the alpha-multiply functions for premultiplied output or rescaling 138333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPInitAlphaProcessing(); 138433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 138533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 1386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Decode. 1387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_DATA; 13880406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, 13898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->height_, ProcessRows)) { 1390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Err; 1391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Cleanup. 1394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora params->last_y = dec->last_out_row_; 1395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LClear(dec); 1396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 1397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err: 1399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LClear(dec); 1400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->status_ != VP8_STATUS_OK); 1401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 1402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1405