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" 19af51b94a435132e9014c324e25fb686b3d07a8c8Vikas 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; 190af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora int huff_codes[NUM_CODE_LENGTH_CODES] = { 0 }; 191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 192af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (!VP8LHuffmanTreeBuildImplicit(&tree, code_length_code_lengths, 193af51b94a435132e9014c324e25fb686b3d07a8c8Vikas 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: 236af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8LHuffmanTreeFree(&tree); 237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ok; 238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 240af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman 241af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora// tree. 242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, 243af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora int* const code_lengths, int* const huff_codes, 244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HuffmanTree* const tree) { 245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 0; 246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int simple_code = VP8LReadBits(br, 1); 248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 249a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (simple_code) { // Read symbols, codes & code lengths directly. 250a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int symbols[2]; 251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int codes[2]; 252a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_symbols = VP8LReadBits(br, 1) + 1; 253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int first_symbol_len_code = VP8LReadBits(br, 1); 254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // The first code is either 1 bit or 8 bit code. 255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); 256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora codes[0] = 0; 257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths[0] = num_symbols - 1; 258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // The second code (if present), is always 8 bit long. 259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_symbols == 2) { 260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora symbols[1] = VP8LReadBits(br, 8); 261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora codes[1] = 1; 262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths[1] = num_symbols - 1; 263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 264af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora ok = VP8LHuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols, 265af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora alphabet_size, num_symbols); 266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // Decode Huffman-coded code lengths. 267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; 269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_codes = VP8LReadBits(br, 4) + 4; 270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_codes > NUM_CODE_LENGTH_CODES) { 271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 275af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); 276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < num_codes; ++i) { 278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); 279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size, 281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora code_lengths); 282af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora ok = ok && VP8LHuffmanTreeBuildImplicit(tree, code_lengths, huff_codes, 283af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora alphabet_size); 284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && !br->error_; 286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, 294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int color_cache_bits, int allow_recursion) { 295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i, j; 296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LMetadata* const hdr = &dec->hdr_; 298a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* huffman_image = NULL; 299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HTreeGroup* htree_groups = NULL; 300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_htree_groups = 1; 301af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora int max_alphabet_size = 0; 302af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora int* code_lengths = NULL; 303af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora int* huff_codes = NULL; 304a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (allow_recursion && VP8LReadBits(br, 1)) { 306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // use meta Huffman codes. 307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_precision = VP8LReadBits(br, 3) + 2; 308a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); 309a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); 310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int huffman_pixs = huffman_xsize * huffman_ysize; 311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, 312a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora &huffman_image)) { 313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Error; 315a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_subsample_bits_ = huffman_precision; 317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < huffman_pixs; ++i) { 318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // The huffman data is stored in red and green bytes. 3191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int group = (huffman_image[i] >> 8) & 0xffff; 3201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora huffman_image[i] = group; 3211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (group >= num_htree_groups) { 3221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora num_htree_groups = group + 1; 323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (br->error_) goto Error; 328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 329af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora // Find maximum alphabet size for the htree group. 330af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { 331af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora int alphabet_size = kAlphabetSize[j]; 332af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (j == 0 && color_cache_bits > 0) { 333af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora alphabet_size += 1 << color_cache_bits; 334af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 335af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (max_alphabet_size < alphabet_size) { 336af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora max_alphabet_size = alphabet_size; 337af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 338af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 339af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora 340af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora htree_groups = VP8LHtreeGroupsNew(num_htree_groups); 341af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora code_lengths = 342af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); 343af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora huff_codes = 344af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora (int*)WebPSafeMalloc((uint64_t)max_alphabet_size, sizeof(*huff_codes)); 345af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora 346af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (htree_groups == NULL || code_lengths == NULL || huff_codes == NULL) { 347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Error; 349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < num_htree_groups; ++i) { 352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora HuffmanTree* const htrees = htree_groups[i].htrees_; 353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { 354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int alphabet_size = kAlphabetSize[j]; 355af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora HuffmanTree* const htree = htrees + j; 356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (j == 0 && color_cache_bits > 0) { 357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora alphabet_size += 1 << color_cache_bits; 358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 359af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, huff_codes, 360af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora htree)) { 361af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora goto Error; 362af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 363a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 365af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(huff_codes); 366af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(code_lengths); 367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // All OK. Finalize pointers and return. 369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_image_ = huffman_image; 370a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->num_htree_groups_ = num_htree_groups; 371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->htree_groups_ = htree_groups; 372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error: 375af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(huff_codes); 376af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(code_lengths); 377af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(huffman_image); 378af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8LHtreeGroupsFree(htree_groups, num_htree_groups); 379a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 381a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 382a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Scaling. 384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { 386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_channels = 4; 387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int in_width = io->mb_w; 388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int out_width = io->scaled_width; 389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int in_height = io->mb_h; 390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int out_height = io->scaled_height; 391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t work_size = 2 * num_channels * (uint64_t)out_width; 392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int32_t* work; // Rescaler work area. 393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t scaled_data_size = num_channels * (uint64_t)out_width; 394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* scaled_data; // Temporary storage for scaled BGRA data. 395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t memory_size = sizeof(*dec->rescaler) + 396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora work_size * sizeof(*work) + 397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora scaled_data_size * sizeof(*scaled_data); 398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory)); 399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (memory == NULL) { 400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->rescaler_memory == NULL); 404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->rescaler_memory = memory; 405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->rescaler = (WebPRescaler*)memory; 407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memory += sizeof(*dec->rescaler); 408a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora work = (int32_t*)memory; 409a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memory += work_size * sizeof(*work); 410a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora scaled_data = (uint32_t*)memory; 411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data, 413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora out_width, out_height, 0, num_channels, 414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora in_width, out_width, in_height, out_height, work); 415a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 416a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 418a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to ARGB 420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// We have special "export" function since we need to convert from BGRA 422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, 423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int rgba_stride, uint8_t* const rgba) { 4248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src = (uint32_t*)rescaler->dst; 425a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int dst_width = rescaler->dst_width; 426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_out = 0; 427a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (WebPRescalerHasPendingOutput(rescaler)) { 428a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const dst = rgba + num_lines_out * rgba_stride; 429af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPRescalerExportRow(rescaler, 0); 4308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRow(src, dst_width, 1); 431a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LConvertFromBGRA(src, dst_width, colorspace, dst); 432a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++num_lines_out; 433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 434a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return num_lines_out; 435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 436a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit scaled rows. 4388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, 4398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* in, int in_stride, int mb_h, 4408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const out, int out_stride) { 441a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WEBP_CSP_MODE colorspace = dec->output_->colorspace; 442a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_in = 0; 443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_out = 0; 444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (num_lines_in < mb_h) { 4458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const row_in = in + num_lines_in * in_stride; 446a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const row_out = out + num_lines_out * out_stride; 4478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int lines_left = mb_h - num_lines_in; 4488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); 4498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(needed_lines > 0 && needed_lines <= lines_left); 4508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRows(row_in, in_stride, 4518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->rescaler->src_width, needed_lines, 0); 4528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); 4538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora num_lines_in += needed_lines; 454a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); 455a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 456a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return num_lines_out; 457a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 458a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 459a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit rows without any scaling. 460a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRows(WEBP_CSP_MODE colorspace, 4618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* row_in, int in_stride, 462a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int mb_w, int mb_h, 463a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const out, int out_stride) { 464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int lines = mb_h; 465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* row_out = out; 466a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (lines-- > 0) { 467a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); 468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora row_in += in_stride; 469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora row_out += out_stride; 470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return mb_h; // Num rows out == num rows in. 472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to YUVA 476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 477af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora// TODO(skal): should be in yuv.c 478a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, 479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPDecBuffer* const output) { 480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPYUVABuffer* const buf = &output->u.YUVA; 481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // first, the luma plane 482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const y = buf->y + y_pos * buf->y_stride; 485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < width; ++i) { 486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t p = src[i]; 4878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, 4888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora YUV_HALF); 489a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // then U/V planes 493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; 495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; 496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int uv_width = width >> 1; 497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < uv_width; ++i) { 499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t v0 = src[2 * i + 0]; 500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t v1 = src[2 * i + 1]; 501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // VP8RGBToU/V expects four accumulated pixels. Hence we need to 502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. 503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); 504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); 505a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); 506a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!(y_pos & 1)) { // even lines: store values 5078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); 5088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); 509a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // odd lines: average with previous values 5108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); 5118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); 512a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Approximated average-of-four. But it's an acceptable diff. 513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u[i] = (u[i] + tmp_u + 1) >> 1; 514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v[i] = (v[i] + tmp_v + 1) >> 1; 515a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 516a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width & 1) { // last pixel 518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t v0 = src[2 * i + 0]; 519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int r = (v0 >> 14) & 0x3fc; 520a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int g = (v0 >> 6) & 0x3fc; 521a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int b = (v0 << 2) & 0x3fc; 522a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!(y_pos & 1)) { // even lines 5238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); 5248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); 525a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // odd lines (note: we could just skip this) 5268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); 5278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); 528a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u[i] = (u[i] + tmp_u + 1) >> 1; 529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v[i] = (v[i] + tmp_v + 1) >> 1; 530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 531a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 532a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 533a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Lastly, store alpha if needed. 534a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (buf->a != NULL) { 535a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 536a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const a = buf->a + y_pos * buf->a_stride; 537a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < width; ++i) a[i] = (src[i] >> 24); 538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 539a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 540a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 541a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { 542a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPRescaler* const rescaler = dec->rescaler; 5438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src = (uint32_t*)rescaler->dst; 544a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int dst_width = rescaler->dst_width; 545a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_out = 0; 546a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (WebPRescalerHasPendingOutput(rescaler)) { 547af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPRescalerExportRow(rescaler, 0); 5488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRow(src, dst_width, 1); 549a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ConvertToYUVA(src, dst_width, y_pos, dec->output_); 550a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++y_pos; 551a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++num_lines_out; 552a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 553a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return num_lines_out; 554a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 555a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 556a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, 5578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* in, int in_stride, int mb_h) { 558a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int num_lines_in = 0; 559a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int y_pos = dec->last_out_row_; 560a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (num_lines_in < mb_h) { 5618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int lines_left = mb_h - num_lines_in; 5628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); 5638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); 5648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); 5658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora num_lines_in += needed_lines; 5668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora in += needed_lines * in_stride; 567a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora y_pos += ExportYUVA(dec, y_pos); 568a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 569a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return y_pos; 570a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 571a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 572a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRowsYUVA(const VP8LDecoder* const dec, 5738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* in, int in_stride, 574a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int mb_w, int num_rows) { 575a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int y_pos = dec->last_out_row_; 576a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (num_rows-- > 0) { 5778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_); 5788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora in += in_stride; 579a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++y_pos; 580a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return y_pos; 582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 583a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Cropping. 586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and 588a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// crop options. Also updates the input data pointer, so that it points to the 5898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// start of the cropped window. Note that pixels are in ARGB format even if 5908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 'in_data' is uint8_t*. 591a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Returns true if the crop window is not empty. 592a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int SetCropWindow(VP8Io* const io, int y_start, int y_end, 5938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t** const in_data, int pixel_stride) { 594a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(y_start < y_end); 595a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(io->crop_left < io->crop_right); 596a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (y_end > io->crop_bottom) { 597a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora y_end = io->crop_bottom; // make sure we don't overflow on last row. 598a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 599a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (y_start < io->crop_top) { 600a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int delta = io->crop_top - y_start; 601a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora y_start = io->crop_top; 6028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora *in_data += delta * pixel_stride; 603a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 604a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (y_start >= y_end) return 0; // Crop window is empty. 605a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 6068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora *in_data += io->crop_left * sizeof(uint32_t); 607a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 608a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_y = y_start - io->crop_top; 609a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_w = io->crop_right - io->crop_left; 610a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_h = y_end - y_start; 611a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; // Non-empty crop window. 612a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 613a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 614a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 615a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 616a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetMetaIndex( 617a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* const image, int xsize, int bits, int x, int y) { 618a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (bits == 0) return 0; 619a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return image[xsize * (y >> bits) + (x >> bits)]; 620a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 621a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 622a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, 623a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int x, int y) { 624a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_, 625a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_subsample_bits_, x, y); 626a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(meta_index < hdr->num_htree_groups_); 627a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return hdr->htree_groups_ + meta_index; 628a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 629a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 631a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Main loop, with custom row-processing function 632a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 633a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); 634a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 635a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, 636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* const rows) { 637a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int n = dec->next_transform_; 638a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int cache_pixs = dec->width_ * num_rows; 639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int start_row = dec->last_row_; 640a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int end_row = start_row + num_rows; 641a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* rows_in = rows; 642a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* const rows_out = dec->argb_cache_; 643a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 644a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Inverse transforms. 645a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // TODO: most transforms only need to operate on the cropped region only. 646a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); 647a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (n-- > 0) { 648a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LTransform* const transform = &dec->transforms_[n]; 649a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); 650a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rows_in = rows_out; 651a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 652a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 653a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 6540406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special method for paletted alpha data. 6550406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, 6560406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t* const rows) { 6570406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int start_row = dec->last_row_; 6580406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int end_row = start_row + num_rows; 6590406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t* rows_in = rows; 6600406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; 6610406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8LTransform* const transform = &dec->transforms_[0]; 6620406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(dec->next_transform_ == 1); 6630406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(transform->type_ == COLOR_INDEXING_TRANSFORM); 6640406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in, 6650406ce1417f76f2034833414dcecc9f56253640cVikas Arora rows_out); 6660406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 6670406ce1417f76f2034833414dcecc9f56253640cVikas Arora 668a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Processes (transforms, scales & color-converts) the rows decoded after the 669a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// last call. 670a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ProcessRows(VP8LDecoder* const dec, int row) { 6710406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; 672a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_rows = row - dec->last_row_; 673a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 674a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_rows <= 0) return; // Nothing to be done. 675a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ApplyInverseTransforms(dec, num_rows, rows); 676a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 677a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Emit output. 678a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 679a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Io* const io = dec->io_; 6808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* rows_data = (uint8_t*)dec->argb_cache_; 6818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA 6828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { 683a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Nothing to output (this time). 684a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 685a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPDecBuffer* const output = dec->output_; 686a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (output->colorspace < MODE_YUV) { // convert to RGBA 687a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPRGBABuffer* const buf = &output->u.RGBA; 688a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; 689a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_rows_out = io->use_scaling ? 6908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, 6918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora rgba, buf->stride) : 692a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora EmitRows(output->colorspace, rows_data, in_stride, 693a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->mb_w, io->mb_h, rgba, buf->stride); 694a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Update 'last_out_row_'. 695a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->last_out_row_ += num_rows_out; 696a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // convert to YUVA 697a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->last_out_row_ = io->use_scaling ? 698a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : 699a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); 700a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 701a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->last_out_row_ <= output->height); 702a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 703a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 704a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 705a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Update 'last_row_'. 706a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->last_row_ = row; 707a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->last_row_ <= dec->height_); 708a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 709a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 7108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Row-processing for the special case when alpha data contains only one 7118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// transform (color indexing), and trivial non-green literals. 7128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int Is8bOptimizable(const VP8LMetadata* const hdr) { 7138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int i; 7148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (hdr->color_cache_size_ > 0) return 0; 7158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // When the Huffman tree contains only one symbol, we can skip the 7168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // call to ReadSymbol() for red/blue/alpha channels. 7178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (i = 0; i < hdr->num_htree_groups_; ++i) { 7188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_; 7198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (htrees[RED].num_nodes_ > 1) return 0; 7208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (htrees[BLUE].num_nodes_ > 1) return 0; 7218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (htrees[ALPHA].num_nodes_ > 1) return 0; 7228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 7240406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 725a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 7268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { 7278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int num_rows = row - dec->last_row_; 7288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* const in = 7298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; 7308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (num_rows > 0) { 7318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ApplyInverseTransformsAlpha(dec, num_rows, in); 7328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_row_ = dec->last_out_row_ = row; 7340406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 735a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 7368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, 7378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int width, int height, int last_row) { 7388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int ok = 1; 7398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int row = dec->last_pixel_ / width; 7408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int col = dec->last_pixel_ % width; 7418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LBitReader* const br = &dec->br_; 7428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LMetadata* const hdr = &dec->hdr_; 7438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); 7448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int pos = dec->last_pixel_; // current position 7458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int end = width * height; // End of data 7468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int last = width * last_row; // Last pixel to decode 7478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; 7488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int mask = hdr->huffman_mask_; 7498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(htree_group != NULL); 750259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi assert(pos < end); 7518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(last_row <= height); 7528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(Is8bOptimizable(hdr)); 7538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 7548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (!br->eos_ && pos < last) { 7558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int code; 7568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Only update when changing tile. 7578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((col & mask) == 0) { 7588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora htree_group = GetHtreeGroupForPos(hdr, col, row); 7598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 7618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora code = ReadSymbol(&htree_group->htrees_[GREEN], br); 7628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (code < NUM_LITERAL_CODES) { // Literal 7638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora data[pos] = code; 7648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++pos; 7658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++col; 7668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (col >= width) { 7678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col = 0; 7688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 7698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (row % NUM_ARGB_CACHE_ROWS == 0) { 7708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ExtractPalettedAlphaRows(dec, row); 7718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (code < len_code_limit) { // Backward reference 7748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int dist_code, dist; 7758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length_sym = code - NUM_LITERAL_CODES; 7768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length = GetCopyLength(length_sym, br); 7778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); 7788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 7798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist_code = GetCopyDistance(dist_symbol, br); 7808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist = PlaneCodeToDistance(width, dist_code); 7818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (pos >= dist && end - pos >= length) { 7828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int i; 7838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist]; 7848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 7858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 7868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 7878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora pos += length; 7898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col += length; 7908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (col >= width) { 7918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col -= width; 7928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 7938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (row % NUM_ARGB_CACHE_ROWS == 0) { 7948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ExtractPalettedAlphaRows(dec, row); 7958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 7978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (pos < last && (col & mask)) { 7988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora htree_group = GetHtreeGroupForPos(hdr, col, row); 7998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { // Not reached 8018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 8028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 8038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = !br->error_; 8058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) goto End; 8068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Process the remaining rows corresponding to last row-block. 8088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ExtractPalettedAlphaRows(dec, row); 8098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 8108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End: 8118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (br->error_ || !ok || (br->eos_ && pos < end)) { 8128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 8138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED 8148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora : VP8_STATUS_BITSTREAM_ERROR; 8158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 8168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_pixel_ = (int)pos; 8178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (pos == end) dec->state_ = READ_DATA; 8188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return ok; 820a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 821a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 8228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, 8238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int width, int height, int last_row, 8248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ProcessRowsFunc process_func) { 8258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int ok = 1; 8268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int row = dec->last_pixel_ / width; 8278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int col = dec->last_pixel_ % width; 8288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LBitReader* const br = &dec->br_; 8298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LMetadata* const hdr = &dec->hdr_; 8308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); 8318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* src = data + dec->last_pixel_; 8328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* last_cached = src; 8338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src_end = data + width * height; // End of data 8348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t* const src_last = data + width * last_row; // Last pixel to decode 8358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; 8368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int color_cache_limit = len_code_limit + hdr->color_cache_size_; 8378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCache* const color_cache = 8388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; 8398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int mask = hdr->huffman_mask_; 8408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(htree_group != NULL); 841259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi assert(src < src_end); 8428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(src_last <= src_end); 8438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 8448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (!br->eos_ && src < src_last) { 8458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int code; 8468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Only update when changing tile. Note we could use this test: 8478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed 8488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // but that's actually slower and needs storing the previous col/row. 8498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((col & mask) == 0) { 8508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora htree_group = GetHtreeGroupForPos(hdr, col, row); 8518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 8538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora code = ReadSymbol(&htree_group->htrees_[GREEN], br); 8548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (code < NUM_LITERAL_CODES) { // Literal 8558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int red, green, blue, alpha; 8568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora red = ReadSymbol(&htree_group->htrees_[RED], br); 8578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora green = code; 8588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 8598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora blue = ReadSymbol(&htree_group->htrees_[BLUE], br); 8608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br); 861af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora *src = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | blue; 8628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora AdvanceByOne: 8638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++src; 8648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++col; 8658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (col >= width) { 8668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col = 0; 8678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 8688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { 8698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora process_func(dec, row); 8708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (color_cache != NULL) { 8728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (last_cached < src) { 8738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCacheInsert(color_cache, *last_cached++); 8748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (code < len_code_limit) { // Backward reference 8788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int dist_code, dist; 8798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length_sym = code - NUM_LITERAL_CODES; 8808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int length = GetCopyLength(length_sym, br); 8818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); 8828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LFillBitWindow(br); 8838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist_code = GetCopyDistance(dist_symbol, br); 8848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dist = PlaneCodeToDistance(width, dist_code); 8858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { 8868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 8878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 8888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 8898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int i; 8908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (i = 0; i < length; ++i) src[i] = src[i - dist]; 8918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora src += length; 8928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 8938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col += length; 8948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (col >= width) { 8958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora col -= width; 8968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ++row; 8978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { 8988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora process_func(dec, row); 8998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (src < src_last) { 9028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); 9038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (color_cache != NULL) { 9048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (last_cached < src) { 9058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCacheInsert(color_cache, *last_cached++); 9068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else if (code < color_cache_limit) { // Color cache 9108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int key = code - len_code_limit; 9118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(color_cache != NULL); 9128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora while (last_cached < src) { 9138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LColorCacheInsert(color_cache, *last_cached++); 9148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora *src = VP8LColorCacheLookup(color_cache, key); 9168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto AdvanceByOne; 9178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { // Not reached 9188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 9198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto End; 9208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = !br->error_; 9228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) goto End; 9238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Process the remaining rows corresponding to last row-block. 9258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (process_func != NULL) process_func(dec, row); 9260406ce1417f76f2034833414dcecc9f56253640cVikas Arora 9278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End: 9288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (br->error_ || !ok || (br->eos_ && src < src_end)) { 9298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = 0; 9308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED 9318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora : VP8_STATUS_BITSTREAM_ERROR; 9328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 9338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_pixel_ = (int)(src - data); 9348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (src == src_end) dec->state_ = READ_DATA; 9358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 9368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return ok; 9378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 9380406ce1417f76f2034833414dcecc9f56253640cVikas Arora 939a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 940a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LTransform 941a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 942a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearTransform(VP8LTransform* const transform) { 943af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(transform->data_); 944a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->data_ = NULL; 945a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 946a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 947a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// For security reason, we need to remap the color map to span 948a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// the total possible bundled values, and not just the num_colors. 949a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExpandColorMap(int num_colors, VP8LTransform* const transform) { 950a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 951a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int final_num_colors = 1 << (8 >> transform->bits_); 952a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* const new_color_map = 953a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, 954a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora sizeof(*new_color_map)); 955a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (new_color_map == NULL) { 956a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 957a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 958a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const data = (uint8_t*)transform->data_; 959a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const new_data = (uint8_t*)new_color_map; 960a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora new_color_map[0] = transform->data_[0]; 961a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 4; i < 4 * num_colors; ++i) { 962a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Equivalent to AddPixelEq(), on a byte-basis. 963a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora new_data[i] = (data[i] + new_data[i - 4]) & 0xff; 964a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 965a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (; i < 4 * final_num_colors; ++i) 966a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora new_data[i] = 0; // black tail. 967af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(transform->data_); 968a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->data_ = new_color_map; 969a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 970a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 971a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 972a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 973a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadTransform(int* const xsize, int const* ysize, 974a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec) { 975a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 1; 976a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 977a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LTransform* transform = &dec->transforms_[dec->next_transform_]; 978a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const VP8LImageTransformType type = 979a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (VP8LImageTransformType)VP8LReadBits(br, 2); 980a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 981a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Each transform type can only be present once in the stream. 982a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec->transforms_seen_ & (1U << type)) { 983a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; // Already there, let's not accept the second same transform. 984a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 985a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->transforms_seen_ |= (1U << type); 986a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 987a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->type_ = type; 988a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->xsize_ = *xsize; 989a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->ysize_ = *ysize; 990a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->data_ = NULL; 991a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++dec->next_transform_; 992a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->next_transform_ <= NUM_TRANSFORMS); 993a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 994a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora switch (type) { 995a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case PREDICTOR_TRANSFORM: 996a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case CROSS_COLOR_TRANSFORM: 997a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_ = VP8LReadBits(br, 3) + 2; 998a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_, 999a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_), 1000a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LSubSampleSize(transform->ysize_, 1001a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_), 1002a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 0, dec, &transform->data_); 1003a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1004a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case COLOR_INDEXING_TRANSFORM: { 1005a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_colors = VP8LReadBits(br, 8) + 1; 1006a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int bits = (num_colors > 16) ? 0 1007a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora : (num_colors > 4) ? 1 1008a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora : (num_colors > 2) ? 2 1009a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora : 3; 1010a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *xsize = VP8LSubSampleSize(transform->xsize_, bits); 1011a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora transform->bits_ = bits; 1012a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_); 1013a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && ExpandColorMap(num_colors, transform); 1014a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1015a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1016a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora case SUBTRACT_GREEN: 1017a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1018a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora default: 1019a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(0); // can't happen 1020a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora break; 1021a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1022a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1023a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ok; 1024a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1025a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1026a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 1027a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LMetadata 1028a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1029a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void InitMetadata(VP8LMetadata* const hdr) { 1030a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(hdr); 1031a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memset(hdr, 0, sizeof(*hdr)); 1032a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1033a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1034a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearMetadata(VP8LMetadata* const hdr) { 1035a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(hdr); 1036a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1037af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(hdr->huffman_image_); 1038af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8LHtreeGroupsFree(hdr->htree_groups_, hdr->num_htree_groups_); 1039a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LColorCacheClear(&hdr->color_cache_); 1040a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora InitMetadata(hdr); 1041a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1042a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1043a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 1044a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LDecoder 1045a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1046a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8LDecoder* VP8LNew(void) { 1047af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); 1048a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return NULL; 1049a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OK; 1050a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_DIM; 1051a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->state_ = READ_DIM; 10528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 10538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDspInit(); // Init critical function pointers. 10548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1055a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return dec; 1056a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1057a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1058a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LClear(VP8LDecoder* const dec) { 1059a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 1060a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return; 1061a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ClearMetadata(&dec->hdr_); 1062a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1063af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(dec->pixels_); 10640406ce1417f76f2034833414dcecc9f56253640cVikas Arora dec->pixels_ = NULL; 1065a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < dec->next_transform_; ++i) { 1066a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ClearTransform(&dec->transforms_[i]); 1067a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1068a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->next_transform_ = 0; 1069a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->transforms_seen_ = 0; 1070a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1071af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(dec->rescaler_memory); 1072a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->rescaler_memory = NULL; 1073a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1074a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->output_ = NULL; // leave no trace behind 1075a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1076a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1077a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LDelete(VP8LDecoder* const dec) { 1078a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec != NULL) { 1079a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LClear(dec); 1080af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(dec); 1081a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1082a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1083a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1084a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void UpdateDecoder(VP8LDecoder* const dec, int width, int height) { 1085a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LMetadata* const hdr = &dec->hdr_; 1086a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_bits = hdr->huffman_subsample_bits_; 1087a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->width_ = width; 1088a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->height_ = height; 1089a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1090a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits); 1091a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1; 1092a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1093a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1094a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int DecodeImageStream(int xsize, int ysize, 1095a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int is_level0, 1096a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec, 1097a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t** const decoded_data) { 1098a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 1; 1099a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int transform_xsize = xsize; 1100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int transform_ysize = ysize; 1101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReader* const br = &dec->br_; 1102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LMetadata* const hdr = &dec->hdr_; 1103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t* data = NULL; 1104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int color_cache_bits = 0; 1105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Read the transforms (may recurse). 1107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (is_level0) { 1108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (ok && VP8LReadBits(br, 1)) { 1109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ReadTransform(&transform_xsize, &transform_ysize, dec); 1110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Color cache 1114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (ok && VP8LReadBits(br, 1)) { 1115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora color_cache_bits = VP8LReadBits(br, 4); 1116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); 1117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 1118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 1119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Read the Huffman codes (may recurse). 1124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, 1125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora color_cache_bits, is_level0); 1126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 1127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 1128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Finish setting up the color-cache 1132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (color_cache_bits > 0) { 1133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->color_cache_size_ = 1 << color_cache_bits; 1134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { 1135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = 0; 1137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora hdr->color_cache_size_ = 0; 1141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora UpdateDecoder(dec, transform_xsize, transform_ysize); 1143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (is_level0) { // level 0 complete 1145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->state_ = READ_HDR; 1146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 1150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; 1151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); 1152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (data == NULL) { 1153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = 0; 1155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto End; 1156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1159a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Use the Huffman trees to decode the LZ77 encoded data. 11608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, 11618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora transform_ysize, NULL); 1162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = ok && !br->error_; 1163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora End: 1165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1166a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 1167af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(data); 1168a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ClearMetadata(hdr); 1169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the 1170a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // status appropriately. 1171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) { 1172a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_SUSPENDED; 1173a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1175a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (decoded_data != NULL) { 1176a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *decoded_data = data; 1177a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 1178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // We allocate image data in this function only for transforms. At level 0 1179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // (that is: not the transforms), we shouldn't have allocated anything. 1180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(data == NULL); 1181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(is_level0); 1182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 11838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls. 1184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. 1185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1186a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ok; 1187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 11900406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Allocate internal buffers dec->pixels_ and dec->argb_cache_. 11918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { 1192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; 1193a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Scratch buffer corresponding to top-prediction row for transforming the 11940406ce1417f76f2034833414dcecc9f56253640cVikas Arora // first row in the row-blocks. Not needed for paletted alpha. 11958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t cache_top_pixels = (uint16_t)final_width; 11960406ce1417f76f2034833414dcecc9f56253640cVikas Arora // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. 11978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; 1198a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t total_num_pixels = 1199a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora num_pixels + cache_top_pixels + cache_pixels; 1200a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->width_ <= final_width); 12028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); 12030406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (dec->pixels_ == NULL) { 1204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->argb_cache_ = NULL; // for sanity check 1205a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1206a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 1207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 12088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; 12098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 12108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 12118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 12128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers8b(VP8LDecoder* const dec) { 12138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_; 12148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->argb_cache_ = NULL; // for sanity check 12158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); 12168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (dec->pixels_ == NULL) { 12178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 12188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 0; 12198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1220a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 1221a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12250406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special row-processing that only stores the alpha data. 1226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ExtractAlphaRows(VP8LDecoder* const dec, int row) { 1227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int num_rows = row - dec->last_row_; 12280406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; 1229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (num_rows <= 0) return; // Nothing to be done. 1231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ApplyInverseTransforms(dec, num_rows, in); 1232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Extract alpha (which is stored in the green plane). 1234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora { 1235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int width = dec->io_->width; // the final width (!= dec->width_) 1236a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int cache_pixs = width * num_rows; 1237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; 1238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t* const src = dec->argb_cache_; 1239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 1240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; 1241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 12420406ce1417f76f2034833414dcecc9f56253640cVikas Arora dec->last_row_ = dec->last_out_row_ = row; 12430406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12458b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, 12468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* const data, size_t data_size, 12478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const output) { 1248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 0; 12498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDecoder* dec; 12508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8Io* io; 12518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(alph_dec != NULL); 12528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->vp8l_dec_ = VP8LNew(); 12538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (alph_dec->vp8l_dec_ == NULL) return 0; 12548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec = alph_dec->vp8l_dec_; 12558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 12568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->width_ = alph_dec->width_; 12578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->height_ = alph_dec->height_; 12588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->io_ = &alph_dec->io_; 12598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io = dec->io_; 1260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8InitIo(io); 12628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used. 12638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io->opaque = output; 12648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io->width = alph_dec->width_; 12658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora io->height = alph_dec->height_; 1266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OK; 1268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInitBitReader(&dec->br_, data, data_size); 1269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_HDR; 12718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { 12728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora goto Err; 12738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12750406ce1417f76f2034833414dcecc9f56253640cVikas Arora // Special case: if alpha data uses only the color indexing transform and 12760406ce1417f76f2034833414dcecc9f56253640cVikas Arora // doesn't use color cache (a frequent case), we will use DecodeAlphaData() 12770406ce1417f76f2034833414dcecc9f56253640cVikas Arora // method that only needs allocation of 1 byte per pixel (alpha channel). 12780406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (dec->next_transform_ == 1 && 12790406ce1417f76f2034833414dcecc9f56253640cVikas Arora dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && 12808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora Is8bOptimizable(&dec->hdr_)) { 12818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->use_8b_decode = 1; 12828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = AllocateInternalBuffers8b(dec); 12838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 12848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Allocate internal buffers (note that dec->width_ may have changed here). 12858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->use_8b_decode = 0; 12868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = AllocateInternalBuffers32b(dec, alph_dec->width_); 12870406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 12880406ce1417f76f2034833414dcecc9f56253640cVikas Arora 12898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) goto Err; 1290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_DATA; 12928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 1293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err: 12958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDelete(alph_dec->vp8l_dec_); 12968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alph_dec->vp8l_dec_ = NULL; 12978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 0; 12988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 12998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 13008b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { 13018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDecoder* const dec = alph_dec->vp8l_dec_; 13028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec != NULL); 13038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec->action_ == READ_DATA); 13048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(last_row <= dec->height_); 13058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1306259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi if (dec->last_pixel_ == dec->width_ * dec->height_) { 1307259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi return 1; // done 1308259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi } 1309259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi 13108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Decode (with special row processing). 13118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return alph_dec->use_8b_decode ? 13128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, 13138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora last_row) : 13148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, 13158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora last_row, ExtractAlphaRows); 1316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1320a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { 1321a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int width, height, has_alpha; 1322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return 0; 1324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (io == NULL) { 1325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_INVALID_PARAM; 1326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 1327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->io_ = io; 1330a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_OK; 1331a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LInitBitReader(&dec->br_, io->data, io->data_size); 1332a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { 1333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 1334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Error; 1335a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->state_ = READ_DIM; 1337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->width = width; 1338a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io->height = height; 1339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1340a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_HDR; 1341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error; 1342a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 1343a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1344a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error: 13450406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8LClear(dec); 13460406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(dec->status_ != VP8_STATUS_OK); 13470406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 1348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeImage(VP8LDecoder* const dec) { 1351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Io* io = NULL; 1352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPDecParams* params = NULL; 1353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Sanity checks. 1355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) return 0; 1356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora io = dec->io_; 1358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(io != NULL); 1359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora params = (WebPDecParams*)io->opaque; 1360a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(params != NULL); 1361a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->output_ = params->output; 1362a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->output_ != NULL); 1363a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Initialization. 1365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { 1366a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = VP8_STATUS_INVALID_PARAM; 1367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Err; 1368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 13708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; 1371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; 1373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1374af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { 1375af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora // need the alpha-multiply functions for premultiplied output or rescaling 1376af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPInitAlphaProcessing(); 1377af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 1378af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora 1379a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Decode. 1380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->action_ = READ_DATA; 13810406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, 13828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->height_, ProcessRows)) { 1383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora goto Err; 1384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Cleanup. 1387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora params->last_y = dec->last_out_row_; 1388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LClear(dec); 1389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; 1390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err: 1392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LClear(dec); 1393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(dec->status_ != VP8_STATUS_OK); 1394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 1395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 1396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1398