1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved. 2466727975bcc57c0c5597bcd0747a2fe4777b303Vikas 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. 8466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// ----------------------------------------------------------------------------- 9466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// 10466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Alpha-plane decompression. 11466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// 12466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Author: Skal (pascal.massimino@gmail.com) 13466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 14466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include <stdlib.h> 158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#include "./alphai.h" 16a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8i.h" 17a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8li.h" 181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include "../utils/quant_levels_dec.h" 19af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora#include "../utils/utils.h" 20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "webp/format_constants.h" 21466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora//------------------------------------------------------------------------------ 238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// ALPHDecoder object. 248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 258b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraALPHDecoder* ALPHNew(void) { 26af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); 278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return dec; 288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 308b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroravoid ALPHDelete(ALPHDecoder* const dec) { 318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (dec != NULL) { 328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora VP8LDelete(dec->vp8l_dec_); 338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->vp8l_dec_ = NULL; 34af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora WebPSafeFree(dec); 358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 37466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Decoding. 408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Initialize alpha decoding by parsing the alpha header and decoding the image 428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// header for alpha data stored using lossless compression. 438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Returns false in case of error in alpha header (data too short, invalid 448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// compression method or filter, error in lossless header data etc). 458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, 468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora size_t data_size, int width, int height, uint8_t* output) { 47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int ok = 0; 480406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; 490406ce1417f76f2034833414dcecc9f56253640cVikas Arora const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; 508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int rsrv; 51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 520406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(width > 0 && height > 0); 53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(data != NULL && output != NULL); 54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->width_ = width; 568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->height_ = height; 578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (data_size <= ALPHA_HEADER_LEN) { 59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 61a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->method_ = (data[0] >> 0) & 0x03; 638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->filter_ = (data[0] >> 2) & 0x03; 648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->pre_processing_ = (data[0] >> 4) & 0x03; 65a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rsrv = (data[0] >> 6) & 0x03; 668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (dec->method_ < ALPHA_NO_COMPRESSION || 678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->method_ > ALPHA_LOSSLESS_COMPRESSION || 688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->filter_ >= WEBP_FILTER_LAST || 698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || 70a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rsrv != 0) { 71a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 72a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (dec->method_ == ALPHA_NO_COMPRESSION) { 758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const size_t alpha_decoded_size = dec->width_ * dec->height_; 760406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok = (alpha_data_size >= alpha_decoded_size); 77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); 798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output); 80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return ok; 828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 83a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha 858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// starting from row number 'row'. It assumes that rows up to (row - 1) have 868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// already been decoded. 878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Returns false in case of bitstream error. 888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { 898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ALPHDecoder* const alph_dec = dec->alph_dec_; 908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int width = alph_dec->width_; 918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int height = alph_dec->height_; 928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_]; 938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint8_t* const output = dec->alpha_plane_; 948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { 958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const size_t offset = row * width; 968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const size_t num_pixels = num_rows * width; 978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels); 988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora memcpy(dec->alpha_plane_ + offset, 998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels); 1008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION 1018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(alph_dec->vp8l_dec_ != NULL); 1028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { 1038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 0; 104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 1058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (unfilter_func != NULL) { 1088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora unfilter_func(width, height, width, row, num_rows, output); 1098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (row + num_rows == dec->pic_hdr_.height_) { 1128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->is_alpha_decoded_ = 1; 1138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return 1; 115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 1188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Main entry point. 119466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 120466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraconst uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, 121466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int row, int num_rows) { 1220406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int width = dec->pic_hdr_.width_; 1230406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int height = dec->pic_hdr_.height_; 124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (row < 0 || num_rows <= 0 || row + num_rows > height) { 126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return NULL; // sanity check. 127466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 128466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (row == 0) { 1308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora // Initialize decoding. 1318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec->alpha_plane_ != NULL); 1328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->alph_dec_ = ALPHNew(); 1338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (dec->alph_dec_ == NULL) return NULL; 1348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, 1358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora width, height, dec->alpha_plane_)) { 1368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ALPHDelete(dec->alph_dec_); 1378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->alph_dec_ = NULL; 1388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return NULL; 139466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 140af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora // if we allowed use of alpha dithering, check whether it's needed at all 141af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { 142af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora dec->alpha_dithering_ = 0; // disable dithering 143af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } else { 144af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora num_rows = height; // decode everything in one pass 145af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 1468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!dec->is_alpha_decoded_) { 1498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int ok = 0; 1508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(dec->alph_dec_ != NULL); 1518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ok = ALPHDecode(dec, row, num_rows); 152af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora if (ok && dec->alpha_dithering_ > 0) { 153af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, 154af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora dec->alpha_dithering_); 155af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora } 1568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok || dec->is_alpha_decoded_) { 1578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ALPHDelete(dec->alph_dec_); 1588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora dec->alph_dec_ = NULL; 1598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (!ok) return NULL; // Error. 161466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Return a pointer to the current decoded row. 1640406ce1417f76f2034833414dcecc9f56253640cVikas Arora return dec->alpha_plane_ + row * width; 165466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 166